From 9c9bd0f9aed6d153b636678b963a1e7f44297e7c Mon Sep 17 00:00:00 2001 From: b1rdmania <102524336+b1rdmania@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:40:00 +0000 Subject: [PATCH] Add FAQ modal and link in header. --- index.html | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.ts | 30 ++++++++++++ 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index e1acf75..057c812 100644 --- a/index.html +++ b/index.html @@ -73,6 +73,103 @@ letter-spacing: 0.05em; text-shadow: var(--glow-primary); } + + .topbar { + display: flex; + align-items: center; + justify-content: center; + gap: calc(var(--spacing-unit) * 2); + margin-bottom: calc(var(--spacing-unit) * 2); + } + .topbar h1 { + margin: 0; + } + .faq-link { + margin-left: auto; + background: transparent; + border: 1px solid rgba(255,255,255,0.14); + color: rgba(255,255,255,0.85); + padding: 8px 10px; + border-radius: var(--radius); + box-shadow: none; + font-size: 13px; + } + .faq-link:hover:not(:disabled) { + box-shadow: var(--shadow-sm); + border-color: rgba(255,255,255,0.22); + } + + /* FAQ modal */ + .modal-backdrop { + position: fixed; + inset: 0; + background: rgba(0,0,0,0.65); + display: none; + align-items: center; + justify-content: center; + padding: 20px; + z-index: 1000; + } + .modal-backdrop.open { display: flex; } + .modal { + width: min(720px, 100%); + background: rgba(20,20,20,0.98); + border: 1px solid rgba(255,255,255,0.12); + border-radius: 12px; + box-shadow: 0 30px 120px rgba(0,0,0,0.75); + overflow: hidden; + } + .modal header { + display: flex; + align-items: center; + gap: 12px; + padding: 14px 16px; + border-bottom: 1px solid rgba(255,255,255,0.08); + } + .modal header h3 { + margin: 0; + font-size: 14px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: rgba(255,255,255,0.9); + } + .modal header .spacer { margin-left: auto; } + .modal header button { + padding: 8px 10px; + border-radius: 10px; + background: rgba(255,255,255,0.06); + border: 1px solid rgba(255,255,255,0.12); + box-shadow: none; + } + .modal main { + padding: 14px 16px 16px 16px; + } + .faq-grid { + display: grid; + grid-template-columns: 1fr; + gap: 12px; + } + .faq-item { + border: 1px solid rgba(255,255,255,0.08); + border-radius: 12px; + padding: 12px 12px; + background: rgba(0,0,0,0.18); + } + .faq-item h4 { + margin: 0 0 6px 0; + font-size: 13px; + color: rgba(0,255,136,0.9); + } + .faq-item p { + margin: 0; + color: rgba(255,255,255,0.75); + font-size: 13px; + line-height: 1.45; + } + .faq-item code { + font-size: 12px; + color: rgba(255,255,255,0.85); + } .controls { margin: calc(var(--spacing-unit) * 3) 0; text-align: center; @@ -662,7 +759,10 @@
-

🎵 MOTIF

+
+

🎵 MOTIF

+ +

Procedural Music Synthesis from MIDI Structure

@@ -782,6 +882,36 @@
+ + \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 9596724..aa86bd5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -52,6 +52,11 @@ class MotifApp { private copyEmbedBtn: HTMLButtonElement | null = null; private copyToast: HTMLElement | null = null; + // FAQ modal + private faqBtn!: HTMLButtonElement; + private faqBackdrop!: HTMLElement; + private faqCloseBtn!: HTMLButtonElement; + private searchResults: any[] = []; private selectedResultIndex = 0; private currentMIDI: { events: NoteEvent[], metadata: any } | null = null; @@ -116,6 +121,11 @@ class MotifApp { this.embedCodeEl = document.getElementById('embedCode'); this.copyEmbedBtn = document.getElementById('copyEmbedBtn') as HTMLButtonElement | null; this.copyToast = document.getElementById('copyToast'); + + // FAQ modal + this.faqBtn = document.getElementById('faqBtn') as HTMLButtonElement; + this.faqBackdrop = document.getElementById('faqModalBackdrop')!; + this.faqCloseBtn = document.getElementById('faqCloseBtn') as HTMLButtonElement; } private setupEventListeners(): void { @@ -159,6 +169,26 @@ class MotifApp { const enable = () => void this.handleEnableAudio(); this.enableAudioBtn.addEventListener('click', enable); this.enableAudioBtn.addEventListener('touchend', enable, { passive: true }); + + // FAQ + this.faqBtn.addEventListener('click', () => this.openFaq()); + this.faqCloseBtn.addEventListener('click', () => this.closeFaq()); + this.faqBackdrop.addEventListener('click', (e) => { + if (e.target === this.faqBackdrop) this.closeFaq(); + }); + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') this.closeFaq(); + }); + } + + private openFaq(): void { + this.faqBackdrop.classList.add('open'); + // focus close for keyboard users + this.faqCloseBtn.focus(); + } + + private closeFaq(): void { + this.faqBackdrop.classList.remove('open'); } private isIOSLike(): boolean {