diff --git a/e2e/timetracker.spec.ts b/e2e/timetracker.spec.ts
index caff92cc..b49063d9 100644
--- a/e2e/timetracker.spec.ts
+++ b/e2e/timetracker.spec.ts
@@ -502,8 +502,10 @@ test.describe('Project Task Dropdown', () => {
await projectOption.getByText(/Tasks/).click();
await page.getByText(taskName, { exact: true }).click();
- // The trigger reflects the selected task.
- await expect(page.getByText(taskName)).toBeVisible();
+ // Scoped to the trigger button: the closing dropdown also contains the name while animating out.
+ await expect(
+ page.getByRole('button', { name: `${projectName} ${taskName}` })
+ ).toBeVisible();
});
test('test that keyboard navigation selects a project', async ({ page, ctx }) => {
@@ -654,7 +656,10 @@ test.describe('Project Task Dropdown', () => {
await search.press('ArrowDown');
await search.press('Enter');
- await expect(page.getByText(taskName)).toBeVisible();
+ // Scoped to the trigger button: the closing dropdown also contains the name while animating out.
+ await expect(
+ page.getByRole('button', { name: `${projectName} ${taskName}` })
+ ).toBeVisible();
});
test('test that pressing space selects the highlighted project', async ({ page, ctx }) => {
diff --git a/resources/js/Components/Common/Member/MemberCombobox.vue b/resources/js/Components/Common/Member/MemberCombobox.vue
index c18e39db..9693e796 100644
--- a/resources/js/Components/Common/Member/MemberCombobox.vue
+++ b/resources/js/Components/Common/Member/MemberCombobox.vue
@@ -89,11 +89,17 @@ function selectMember(member: Member) {
+
+ :filter-function="(val: string[]) => val"
+ @update:open="
+ (value: boolean) => {
+ if (!value) open = false;
+ }
+ ">
clients.value.filter((c) => !c.is_archived));
-// The selected project is pinned when the dropdown opens so rows don't re-sort while
-// the user interacts, but the project list itself stays reactive — projects may still
-// be loading (fetchAllPages) when the dropdown opens.
+// Pinned on open so rows don't re-sort while interacting; the project list itself stays reactive.
const pinnedProjectId = ref(null);
const sortedProjects = computed(() => {
@@ -112,13 +110,19 @@ function updateValue(project: Project) {
-
+
+
+ @update:model-value="updateValue"
+ @update:open="
+ (value: boolean) => {
+ if (!value) open = false;
+ }
+ ">
-
+
+ @update:model-value="updateValue"
+ @update:open="
+ (value: boolean) => {
+ if (!value) open = false;
+ }
+ ">
>(new Set());
watch(open, (isOpen) => {
@@ -104,7 +102,16 @@ const emit = defineEmits(['update:modelValue', 'changed', 'submit']);
-
+
+ {
+ if (!value) open = false;
+ }
+ ">
({
const open = ref(false);
const searchValue = ref('');
-// The selection is pinned when the dropdown opens so rows don't re-sort while the user
-// toggles tags, but the tag list itself stays reactive — tags may still be loading
-// when the dropdown opens.
+// Pinned on open so rows don't re-sort while toggling; the tag list itself stays reactive.
const pinnedSelection = ref>(new Set());
watch(open, (isOpen) => {
diff --git a/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue b/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue
index ea8275af..4f03d53c 100644
--- a/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue
+++ b/resources/js/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue
@@ -594,7 +594,7 @@ const showCreateProject = ref(false);
-