fix(ux): improve microinteractions across the app
1. Nav-item tap: smooth scale transition instead of abrupt snap 2. Custom toggle switch: iOS-style toggle replaces native checkboxes 3. Focus-visible: outline on cards, buttons, FABs for keyboard users 4. Empty-state: gentle fade-in animation 5. Toast icons: SVG icons for success/danger/warning types 6. Swipe haptic: vibrate(15) fires at threshold during touchmove
This commit is contained in:
@@ -377,9 +377,10 @@ function openBudgetModal({ mode, entry = null }) {
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="allday-toggle">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" id="bm-recurring" ${isEdit && entry.is_recurring ? 'checked' : ''}>
|
||||
<span class="allday-toggle__label">${t('budget.recurringLabel')}</span>
|
||||
<span class="toggle__track"></span>
|
||||
<span>${t('budget.recurringLabel')}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -795,9 +795,10 @@ function buildEventModalContent({ mode, event, date }) {
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="allday-toggle">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" id="modal-allday" ${isEdit && event.all_day ? 'checked' : ''}>
|
||||
<span class="allday-toggle__label">${t('calendar.allDayToggle')}</span>
|
||||
<span class="toggle__track"></span>
|
||||
<span>${t('calendar.allDayToggle')}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -379,9 +379,10 @@ function openNoteModal({ mode, note = null }) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="allday-toggle">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" id="note-pinned" ${isEdit && note.pinned ? 'checked' : ''}>
|
||||
<span class="allday-toggle__label">${t('notes.pinnedLabel')}</span>
|
||||
<span class="toggle__track"></span>
|
||||
<span>${t('notes.pinnedLabel')}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -350,6 +350,7 @@ function wireSwipeGestures(container) {
|
||||
let startX = 0, startY = 0;
|
||||
let dx = 0;
|
||||
let locked = false; // false | 'swipe' | 'scroll'
|
||||
let thresholdHit = false;
|
||||
const card = row.querySelector('.shopping-item');
|
||||
if (!card) return;
|
||||
|
||||
@@ -367,6 +368,7 @@ function wireSwipeGestures(container) {
|
||||
startY = e.touches[0].clientY;
|
||||
dx = 0;
|
||||
locked = false;
|
||||
thresholdHit = false;
|
||||
card.style.transition = '';
|
||||
}, { passive: true });
|
||||
|
||||
@@ -408,6 +410,12 @@ function wireSwipeGestures(container) {
|
||||
row.querySelector('.swipe-reveal--delete').style.opacity = String(progress);
|
||||
row.querySelector('.swipe-reveal--done').style.opacity = '0';
|
||||
}
|
||||
|
||||
// Haptic-Feedback beim Erreichen des Schwellwerts
|
||||
if (!thresholdHit && Math.abs(dx) >= SWIPE_THRESHOLD) {
|
||||
thresholdHit = true;
|
||||
vibrate(15);
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
row.addEventListener('touchend', async () => {
|
||||
|
||||
@@ -730,6 +730,7 @@ function wireSwipeGestures(container) {
|
||||
let startX = 0, startY = 0;
|
||||
let dx = 0;
|
||||
let locked = false; // false = unentschieden, 'swipe' | 'scroll'
|
||||
let thresholdHit = false; // Haptic-Feedback am Threshold nur einmal
|
||||
const card = row.querySelector('.task-card');
|
||||
if (!card) return;
|
||||
|
||||
@@ -749,6 +750,7 @@ function wireSwipeGestures(container) {
|
||||
startY = e.touches[0].clientY;
|
||||
dx = 0;
|
||||
locked = false;
|
||||
thresholdHit = false;
|
||||
card.style.transition = '';
|
||||
}, { passive: true });
|
||||
|
||||
@@ -794,6 +796,12 @@ function wireSwipeGestures(container) {
|
||||
row.querySelector('.swipe-reveal--edit').style.opacity = String(progress);
|
||||
row.querySelector('.swipe-reveal--done').style.opacity = '0';
|
||||
}
|
||||
|
||||
// Haptic-Feedback beim Erreichen des Schwellwerts
|
||||
if (!thresholdHit && Math.abs(dx) >= SWIPE_THRESHOLD) {
|
||||
thresholdHit = true;
|
||||
vibrate(15);
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
row.addEventListener('touchend', async () => {
|
||||
|
||||
Reference in New Issue
Block a user