fix focus state for dropdowns, fix taborder for timerange select in timetracker and timeentryrows

This commit is contained in:
Gregor Vostrak
2025-01-29 13:16:54 +01:00
parent b783ea9ecd
commit 2dd80ba6cc
8 changed files with 68 additions and 50 deletions

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import Dropdown from '@/packages/ui/src/Input/Dropdown.vue';
import { computed, ref, watch } from 'vue';
import { computed, ref } from 'vue';
import TimeRangeSelector from '@/packages/ui/src/Input/TimeRangeSelector.vue';
import dayjs, { Dayjs } from 'dayjs';
import parse from 'parse-duration';
@@ -28,8 +28,8 @@ function pauseLiveTimerUpdate(event: FocusEvent) {
function onTimeEntryEnterPress() {
updateTimerAndStartLiveTimerUpdate();
const activeElement = document.activeElement as HTMLElement;
activeElement?.blur();
//const activeElement = document.activeElement as HTMLElement;
// activeElement?.blur();
}
const currentTime = computed({
@@ -111,6 +111,7 @@ function isHHMM(value: string): boolean {
function parseHHMM(value: string): string[] | null {
return value.match(HHMMtimeRegex);
}
const temporaryCustomTimerEntry = ref<string>('');
async function updateTimeRange(newStart: string) {
@@ -132,11 +133,31 @@ const startTime = computed(() => {
return dayjs().utc().format();
});
const inputField = ref<HTMLInputElement | null>(null);
watch(open, (isOpen) => {
if (!isOpen) {
inputField.value?.focus();
const timeRangeSelector = ref<HTMLElement | null>(null);
function openModalOnTab(e: FocusEvent) {
// check if the source is inside the dropdown
const source = e.relatedTarget as HTMLElement;
if (source && window.document.body.contains(source)) {
open.value = true;
}
});
}
function focusNextElement(e: KeyboardEvent) {
if (open.value) {
e.preventDefault();
const focusableElement = timeRangeSelector.value?.querySelector<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
focusableElement?.focus();
}
}
function closeAndFocusInput() {
inputField.value?.focus();
open.value = false;
}
</script>
<template>
@@ -150,20 +171,26 @@ watch(open, (isOpen) => {
<input
placeholder="00:00:00"
@focus="pauseLiveTimerUpdate"
@focusin="openModalOnTab"
@keydown.exact.tab="focusNextElement"
@keydown.exact.shift.tab="open = false"
ref="inputField"
data-testid="time_entry_time"
@blur="updateTimerAndStartLiveTimerUpdate"
@keydown.enter="onTimeEntryEnterPress"
v-model="currentTime"
class="w-[110px] lg:w-[130px] h-full text-white py-2.5 rounded-r-lg text-center px-4 text-base lg:text-lg font-bold bg-card-background border-none placeholder-muted focus:ring-0 transition"
class="w-[110px] lg:w-[130px] h-full text-white py-2.5 rounded-lg border-border-secondary border text-center px-4 text-base lg:text-lg font-bold bg-card-background border-none placeholder-muted focus:ring-0 transition"
type="text" />
</template>
<template #content>
<TimeRangeSelector
@changed="updateTimeRange"
:start="startTime"
:end="null">
</TimeRangeSelector>
<div ref="timeRangeSelector">
<TimeRangeSelector
@changed="updateTimeRange"
@close="closeAndFocusInput"
:start="startTime"
:end="null">
</TimeRangeSelector>
</div>
</template>
</Dropdown>
</div>