From 9fd3fbca8b3e62d63ca5cdf5a4c4fecc6358b886 Mon Sep 17 00:00:00 2001 From: Michael Genson <71845777+michael-genson@users.noreply.github.com> Date: Sun, 10 May 2026 13:15:20 -0500 Subject: [PATCH] feat: Improve new shopping list UI (#7600) Co-authored-by: Copilot --- .../ShoppingList/ShoppingListAddItemForm.vue | 50 +++++++++++++------ .../Domain/ShoppingList/ShoppingListItem.vue | 23 ++++++--- .../ShoppingList/ShoppingListItemDetails.vue | 5 ++ .../app/components/global/InputLabelType.vue | 4 ++ frontend/app/lang/messages/en-US.json | 2 +- frontend/app/pages/shopping-lists/[id].vue | 26 +++++----- 6 files changed, 77 insertions(+), 33 deletions(-) diff --git a/frontend/app/components/Domain/ShoppingList/ShoppingListAddItemForm.vue b/frontend/app/components/Domain/ShoppingList/ShoppingListAddItemForm.vue index ba2c4d71b..4a3dcf836 100644 --- a/frontend/app/components/Domain/ShoppingList/ShoppingListAddItemForm.vue +++ b/frontend/app/components/Domain/ShoppingList/ShoppingListAddItemForm.vue @@ -11,18 +11,28 @@ >
- +
+ + +
+
void } | null>(null); +const rail = ref(true); + +async function expandAndFocus() { + rail.value = false; + await nextTick(); + setTimeout(() => { + foodInputRef.value?.focus(); + }, 200); +} + watch( () => listItem.value.quantity, (newQty) => { @@ -100,6 +124,4 @@ watch( listItem.value.labelId = listItem.value.label?.id || null; }, ); - -const rail = ref(true); diff --git a/frontend/app/components/Domain/ShoppingList/ShoppingListItem.vue b/frontend/app/components/Domain/ShoppingList/ShoppingListItem.vue index b197c6b65..2ecefd99d 100644 --- a/frontend/app/components/Domain/ShoppingList/ShoppingListItem.vue +++ b/frontend/app/components/Domain/ShoppingList/ShoppingListItem.vue @@ -11,11 +11,13 @@ > (); const { assignLabelToFood, createAssignUnit } = useShoppingListItemEditor(listItem); +const { smAndDown } = useDisplay(); +const menuDirection = computed(() => smAndDown.value ? "top" : "bottom"); + function handleNoteKeyPress(event: KeyboardEvent) { // Save on Enter if (!event.shiftKey && event.key === "Enter") { diff --git a/frontend/app/components/global/InputLabelType.vue b/frontend/app/components/global/InputLabelType.vue index 74fc6e462..eba29551a 100644 --- a/frontend/app/components/global/InputLabelType.vue +++ b/frontend/app/components/global/InputLabelType.vue @@ -93,4 +93,8 @@ function emitCreate() { emit("create", searchInput.value); autocompleteRef.value?.blur(); } + +defineExpose({ + focus: () => autocompleteRef.value?.focus(), +}); diff --git a/frontend/app/lang/messages/en-US.json b/frontend/app/lang/messages/en-US.json index 01ed8f24c..82de408c6 100644 --- a/frontend/app/lang/messages/en-US.json +++ b/frontend/app/lang/messages/en-US.json @@ -943,7 +943,7 @@ "are-you-sure-you-want-to-uncheck-all-items": "Are you sure you want to uncheck all items?", "are-you-sure-you-want-to-delete-checked-items": "Are you sure you want to delete all checked items?", "no-shopping-lists-found": "No Shopping Lists Found", - "item-checked-off": "{item} was checked off" + "item-checked-off": "Checked off {item}" }, "sidebar": { "all-recipes": "All Recipes", diff --git a/frontend/app/pages/shopping-lists/[id].vue b/frontend/app/pages/shopping-lists/[id].vue index 7138c7378..6b289c0d8 100644 --- a/frontend/app/pages/shopping-lists/[id].vue +++ b/frontend/app/pages/shopping-lists/[id].vue @@ -377,20 +377,22 @@ const { store: allUnits } = useUnitStore(); const { store: allFoods } = useFoodStore(); function itemCheckedToast(item: ShoppingListItemOut) { - alert.info( - i18n.t("shopping-list.item-checked-off", { item: item.food?.name || item.note || i18n.t("recipe.ingredient") }), - undefined, - { - timeout: 4000, - action: { - message: i18n.t("general.undo"), - onClick: () => { - item.checked = false; - shoppingListPage.saveListItem(item); + setTimeout(() => { + alert.info( + i18n.t("shopping-list.item-checked-off", { item: item.food?.name || item.note || i18n.t("recipe.ingredient") }), + undefined, + { + timeout: 4000, + action: { + message: i18n.t("general.undo"), + onClick: () => { + item.checked = false; + shoppingListPage.saveListItem(item); + }, }, }, - }, - ); + ); + }, 500); } const {