|
34 | 34 | onMount(() => { |
35 | 35 | const mq = window.matchMedia('(prefers-color-scheme: dark)') |
36 | 36 | isDark = mq.matches |
37 | | - const onMq = (e: MediaQueryListEvent) => isDark = e.matches |
| 37 | + document.documentElement.classList.toggle('dark', isDark) |
| 38 | + const onMq = (e: MediaQueryListEvent) => { |
| 39 | + isDark = e.matches |
| 40 | + document.documentElement.classList.toggle('dark', isDark) |
| 41 | + } |
38 | 42 | mq.addEventListener('change', onMq) |
39 | 43 |
|
40 | 44 | const onHashChange = () => { |
|
138 | 142 | } |
139 | 143 | </script> |
140 | 144 |
|
141 | | -<div class="absolute inset-0 flex flex-col font-sans {isDark ? 'bg-[#0d1117] text-[#c9d1d9]' : 'bg-[#f6f8fa] text-[#1f2328]'}"> |
142 | | - <div class="flex items-stretch gap-1 p-1.5 border-b {isDark ? 'border-[#1c2128] bg-[#0d1117]' : 'border-[#d0d7de] bg-[#ffffff]'}"> |
| 145 | +<div class="absolute inset-0 flex flex-col font-sans bg-base color-base"> |
| 146 | + <div class="flex items-stretch gap-1 p-1.5 border-b border-base bg-base"> |
143 | 147 | <div class="flex gap-1 overflow-x-auto flex-1 items-center"> |
144 | 148 | {#each sessions as s (s.id)} |
145 | 149 | {#if renamingId === s.id} |
146 | 150 | <input |
147 | | - class="font-inherit text-xs w-[10ch] min-w-[64px] px-1 py-0.5 border rounded outline-none {isDark ? 'border-[#58a6ff] bg-[#0d1117] text-[#c9d1d9]' : 'border-[#0969da] bg-[#ffffff] text-[#1f2328]'}" |
| 151 | + class="font-mono text-xs w-[10ch] min-w-[64px] px-1 py-0.5 border rounded outline-none border-active bg-base color-base" |
148 | 152 | value={displayName(s)} |
149 | 153 | spellcheck={false} |
150 | 154 | onkeydown={(e) => { |
|
157 | 161 | /> |
158 | 162 | {:else} |
159 | 163 | <button |
160 | | - class="inline-flex items-center gap-1.5 whitespace-nowrap px-2.5 py-1 rounded-md border text-xs cursor-pointer transition-colors |
161 | | - {activeId === s.id |
162 | | - ? (isDark ? 'bg-[#21262d] text-white border-[#30363d]' : 'bg-[#ffffff] text-[#1f2328] border-[#d0d7de]') |
163 | | - : (isDark ? 'bg-[#161b22] text-[#8b949e] border-transparent hover:text-[#c9d1d9]' : 'bg-[#ffffff] text-[#59636e] border-transparent hover:text-[#1f2328]')}" |
| 164 | + class="tab-btn {activeId === s.id ? 'tab-btn-active' : ''}" |
164 | 165 | title="Double-click to rename" |
165 | 166 | onclick={() => activeId = s.id} |
166 | 167 | ondblclick={(e) => { e.preventDefault(); e.stopPropagation(); renamingId = s.id }} |
167 | 168 | > |
168 | 169 | <span class="w-1.5 h-1.5 rounded-full shrink-0 |
169 | | - {s.status === 'running' ? 'bg-[#3fb950]' : s.status === 'exited' ? 'bg-[#6e7681]' : 'bg-[#f85149]'}"> |
| 170 | + {s.status === 'running' ? 'bg-green-500' : s.status === 'exited' ? 'bg-gray-500' : 'bg-red-500'}"> |
170 | 171 | </span> |
171 | 172 | <span>{displayName(s)}</span> |
172 | 173 | </button> |
173 | 174 | {/if} |
174 | 175 | {/each} |
175 | 176 | <button |
176 | | - class="min-w-[28px] justify-center font-semibold text-sm flex-none inline-flex items-center whitespace-nowrap px-2 py-1 rounded-md border border-transparent cursor-pointer transition-colors |
177 | | - {isDark ? 'bg-[#161b22] text-[#8b949e] hover:text-[#c9d1d9]' : 'bg-[#ffffff] text-[#59636e] hover:text-[#1f2328]'}" |
| 177 | + class="tab-btn px-2 min-w-[28px] justify-center" |
178 | 178 | title="New terminal" |
179 | 179 | onclick={() => spawn({ mode: 'interactive' })} |
180 | 180 | > |
|
184 | 184 |
|
185 | 185 | <div class="flex gap-1.5 items-center"> |
186 | 186 | <select |
187 | | - class="px-2 py-1 rounded-md border text-xs outline-none |
188 | | - {isDark ? 'border-[#30363d] bg-[#21262d] text-[#c9d1d9]' : 'border-[#d0d7de] bg-[#ffffff] text-[#1f2328]'}" |
| 187 | + class="px-2 py-1 rounded-md border text-xs outline-none border-base bg-secondary color-base" |
189 | 188 | disabled={presets.length === 0} |
190 | 189 | onchange={handleSelectPreset} |
191 | 190 | > |
|
197 | 196 | </div> |
198 | 197 | </div> |
199 | 198 |
|
200 | | - <div class="flex items-center gap-2 px-2.5 py-1 border-b text-xs min-h-[20px] {isDark ? 'border-[#1c2128] text-[#8b949e]' : 'border-[#d0d7de] text-[#59636e]'}"> |
| 199 | + <div class="flex items-center gap-2 px-2.5 py-1 border-b text-xs min-h-[20px] border-base text-gray-500 dark:text-gray-400"> |
201 | 200 | {#if activeId} |
202 | 201 | {@const activeSession = sessions.find(s => s.id === activeId)} |
203 | 202 | {#if activeSession} |
204 | | - <span class="px-1.5 py-0.5 rounded-full text-[10px] uppercase tracking-wide border |
205 | | - {activeSession.mode === 'interactive' ? (isDark ? 'text-[#58a6ff] border-[#1f6feb55]' : 'text-[#0969da] border-[#0969da55]') : (isDark ? 'text-[#d29922] border-[#9e6a0355]' : 'text-[#bb8009] border-[#9e6a0355]')}"> |
| 203 | + <span class="px-1.5 py-0.5 rounded-full text-[10px] uppercase tracking-wide border {activeSession.mode === 'interactive' ? 'color-active border-active bg-active' : 'text-amber-600 dark:text-amber-500 border-amber-500/25 bg-amber-500/10'}"> |
206 | 204 | {activeSession.mode} |
207 | 205 | </span> |
208 | | - <span class="font-mono {isDark ? 'text-[#c9d1d9]' : 'text-[#1f2328]'}"> |
| 206 | + <span class="font-mono color-base"> |
209 | 207 | {activeSession.command}{activeSession.args.length ? ` ${activeSession.args.join(' ')}` : ''} |
210 | 208 | </span> |
211 | 209 | <span> |
|
214 | 212 | : `${activeSession.status}${activeSession.exitCode != null ? ` (${activeSession.exitCode})` : ''}`} |
215 | 213 | </span> |
216 | 214 | <div class="flex-1"></div> |
217 | | - <button class="px-2.5 py-1 rounded-md border text-xs cursor-pointer {isDark ? 'border-[#30363d] bg-[#21262d] text-[#c9d1d9] hover:bg-[#30363d]' : 'border-[#d0d7de] bg-[#ffffff] text-[#1f2328] hover:bg-[#eaeef2]'}" onclick={() => rpc.call('devframes-plugin-terminals:restart', { id: activeSession.id }).catch(() => {})}> |
218 | | - <div class="i-ph:arrows-clockwise mr-1 inline-block align-text-bottom"></div> Restart |
| 215 | + <button class="btn-action" onclick={() => rpc.call('devframes-plugin-terminals:restart', { id: activeSession.id }).catch(() => {})}> |
| 216 | + <div class="i-ph:arrows-clockwise"></div> Restart |
219 | 217 | </button> |
220 | | - <button class="px-2.5 py-1 rounded-md border text-xs cursor-pointer {isDark ? 'border-[#30363d] bg-[#21262d] text-[#c9d1d9] hover:bg-[#30363d]' : 'border-[#d0d7de] bg-[#ffffff] text-[#1f2328] hover:bg-[#eaeef2]'}" onclick={() => rpc.call('devframes-plugin-terminals:remove', { id: activeSession.id }).catch(() => {})}> |
221 | | - <div class="i-ph:trash mr-1 inline-block align-text-bottom"></div> Kill |
| 218 | + <button class="btn-action" onclick={() => rpc.call('devframes-plugin-terminals:remove', { id: activeSession.id }).catch(() => {})}> |
| 219 | + <div class="i-ph:trash"></div> Kill |
222 | 220 | </button> |
223 | 221 | {/if} |
224 | 222 | {/if} |
225 | 223 | </div> |
226 | 224 |
|
227 | 225 | <div class="relative flex-1 overflow-hidden {isDark ? 'bg-black' : 'bg-white'}"> |
228 | 226 | {#if sessions.length === 0} |
229 | | - <div class="absolute inset-0 flex items-center justify-center text-[13px] pointer-events-none {isDark ? 'text-[#6e7681]' : 'text-[#59636e]'}"> |
| 227 | + <div class="absolute inset-0 flex items-center justify-center text-[13px] pointer-events-none text-gray-400 dark:text-gray-500"> |
230 | 228 | No terminal sessions — click + to start one. |
231 | 229 | </div> |
232 | 230 | {/if} |
|
0 commit comments