Skip to content

Commit 9038891

Browse files
committed
fix: sticky save header hidden behind fixed nav bar
1 parent 28c3959 commit 9038891

1 file changed

Lines changed: 45 additions & 7 deletions

File tree

src/lib/components/ConfigEditor.svelte

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,34 @@
2121
let editingConfig = $state<any>(null);
2222
let showScriptModal = $state(false);
2323
let scriptDraft = $state('');
24+
let scriptTextarea: HTMLTextAreaElement | undefined = $state();
25+
let lineNumbers = $derived((() => {
26+
const count = (scriptDraft || '').split('\n').length;
27+
return Array.from({ length: Math.max(count, 1) }, (_, i) => i + 1);
28+
})());
29+
30+
function syncLineScroll(e: Event) {
31+
const textarea = e.target as HTMLTextAreaElement;
32+
const gutter = textarea.parentElement?.querySelector('.line-gutter') as HTMLElement | null;
33+
if (gutter) {
34+
gutter.scrollTop = textarea.scrollTop;
35+
}
36+
}
37+
38+
function handleEditorKeydown(e: KeyboardEvent) {
39+
if (e.key === 'Tab') {
40+
e.preventDefault();
41+
const ta = e.target as HTMLTextAreaElement;
42+
const start = ta.selectionStart;
43+
const end = ta.selectionEnd;
44+
const value = ta.value;
45+
scriptDraft = value.substring(0, start) + '\t' + value.substring(end);
46+
// Restore cursor after tick
47+
requestAnimationFrame(() => {
48+
ta.selectionStart = ta.selectionEnd = start + 1;
49+
});
50+
}
51+
}
2452
2553
let formData = $state({
2654
name: '',
@@ -652,12 +680,22 @@
652680
</div>
653681
</div>
654682
<div class="script-modal-body">
655-
<textarea
656-
class="script-modal-textarea"
657-
bind:value={scriptDraft}
658-
placeholder="#!/bin/bash&#10;# Commands to run after package installation&#10;&#10;# Example:&#10;# mkdir -p ~/Projects&#10;# npm install -g vercel&#10;# defaults write com.apple.dock autohide -bool true"
659-
spellcheck="false"
660-
></textarea>
683+
<div class="code-editor">
684+
<div class="line-gutter" aria-hidden="true">
685+
{#each lineNumbers as num}
686+
<div class="line-number">{num}</div>
687+
{/each}
688+
</div>
689+
<textarea
690+
class="script-modal-textarea"
691+
bind:this={scriptTextarea}
692+
bind:value={scriptDraft}
693+
placeholder="#!/bin/bash&#10;# Commands to run after package installation&#10;&#10;# Example:&#10;# mkdir -p ~/Projects&#10;# npm install -g vercel&#10;# defaults write com.apple.dock autohide -bool true"
694+
spellcheck="false"
695+
onscroll={syncLineScroll}
696+
onkeydown={handleEditorKeydown}
697+
></textarea>
698+
</div>
661699
</div>
662700
<div class="script-modal-hint">
663701
Commands run sequentially in your home directory after packages, shell, dotfiles, and macOS preferences are applied.
@@ -698,7 +736,7 @@
698736
/* Header */
699737
.editor-header {
700738
position: sticky;
701-
top: 0;
739+
top: 53px;
702740
z-index: 40;
703741
display: flex;
704742
justify-content: space-between;

0 commit comments

Comments
 (0)