feat: Add CMD+K command palette with ninja-keys integration
Implement a command palette accessible via CMD+K/Ctrl+K using the ninja-keys web component. Features include: - New /api/cmd-k endpoint serving dynamic CV entries (experiences, projects, courses) - Language-aware responses with 1-hour cache headers - Scroll-to-section functionality for quick navigation - Enhanced keyboard shortcuts modal with CMD+K documentation - Comprehensive test coverage for API and UI interactions Also includes cleanup of deprecated debug test files and various UI polish improvements to contact form, themes, and action bar components.
This commit is contained in:
@@ -1,7 +1,21 @@
|
||||
{{define "contact-modal"}}
|
||||
<!-- Contact Form Modal - Native Dialog -->
|
||||
<dialog id="contact-modal" class="info-modal no-print"
|
||||
_="on click call closeOnBackdrop(me, event)">
|
||||
_="on click call closeOnBackdrop(me, event)
|
||||
on show
|
||||
-- Reset form state when modal opens
|
||||
set form to getElementById('contact-form')
|
||||
if form
|
||||
call form.reset()
|
||||
set formFields to querySelectorAll('.form-group') in form
|
||||
repeat for field in formFields
|
||||
remove .hidden from field
|
||||
end
|
||||
remove .hidden from querySelector('.form-actions') in form
|
||||
remove .hidden from querySelector('.form-note') in form
|
||||
set responseDiv to getElementById('contact-response')
|
||||
if responseDiv set responseDiv.innerHTML to ''
|
||||
end">
|
||||
<div class="info-modal-content">
|
||||
<button class="info-modal-close" onclick="document.getElementById('contact-modal').close()" aria-label="{{.UI.ContactModal.Close}}">
|
||||
<iconify-icon icon="mdi:close" width="24" height="24"></iconify-icon>
|
||||
@@ -25,11 +39,21 @@
|
||||
hx-target="#contact-response"
|
||||
hx-swap="innerHTML"
|
||||
hx-indicator="#contact-spinner"
|
||||
hx-headers='{"X-Requested-With": "htmx"}'
|
||||
hx-headers='{"X-Requested-With": "XMLHttpRequest"}'
|
||||
_="on htmx:afterRequest
|
||||
if event.detail.successful
|
||||
wait 2s then call document.getElementById('contact-modal').close()
|
||||
end">
|
||||
-- Check if response contains success message (not validation error)
|
||||
set responseDiv to document.getElementById('contact-response')
|
||||
if responseDiv is not null and responseDiv.querySelector('.contact-success') is not null
|
||||
-- Hide all form fields and show only success message
|
||||
set formFields to me.querySelectorAll('.form-group')
|
||||
repeat for field in formFields
|
||||
add .hidden to field
|
||||
end
|
||||
add .hidden to me.querySelector('.form-actions')
|
||||
add .hidden to me.querySelector('.form-note')
|
||||
-- Close modal after 3 seconds
|
||||
wait 3s then call document.getElementById('contact-modal').close()
|
||||
end">
|
||||
|
||||
<!-- Honeypot field - hidden, should be empty -->
|
||||
<div style="position: absolute; left: -9999px;" aria-hidden="true">
|
||||
@@ -134,29 +158,37 @@
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<!-- Initialize form timestamp on page load -->
|
||||
<!-- Initialize form timestamp on page load and modal open -->
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
function resetContactFormTimestamp() {
|
||||
const timestampField = document.getElementById('contact-form-loaded-at');
|
||||
if (timestampField) {
|
||||
timestampField.value = Date.now();
|
||||
}
|
||||
});
|
||||
|
||||
// Reset timestamp when modal opens
|
||||
const contactModal = document.getElementById('contact-modal');
|
||||
if (contactModal) {
|
||||
contactModal.addEventListener('click', function(e) {
|
||||
if (e.target === contactModal && contactModal.open) {
|
||||
const timestampField = document.getElementById('contact-form-loaded-at');
|
||||
if (timestampField) {
|
||||
timestampField.value = Date.now();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set initial timestamp on page load
|
||||
document.addEventListener('DOMContentLoaded', resetContactFormTimestamp);
|
||||
|
||||
// Reset timestamp when modal opens (using MutationObserver to catch dialog open)
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const contactModal = document.getElementById('contact-modal');
|
||||
if (contactModal) {
|
||||
// Observer watches for the 'open' attribute being added
|
||||
const observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
if (mutation.attributeName === 'open' && contactModal.hasAttribute('open')) {
|
||||
resetContactFormTimestamp();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(contactModal, { attributes: true });
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user