diff --git a/apps/web/src/features/recipes/IngredientPicker.tsx b/apps/web/src/features/recipes/IngredientPicker.tsx index 3357e39..79c18fc 100644 --- a/apps/web/src/features/recipes/IngredientPicker.tsx +++ b/apps/web/src/features/recipes/IngredientPicker.tsx @@ -7,7 +7,7 @@ import { } from "@batch-cooking/shared"; import { useState } from "react"; import { useTranslation } from "react-i18next"; -import { AllergenIcon, DietPreferencesIcon } from "../../layouts/nav-icons"; +import { SettingsIcon } from "../../layouts/nav-icons"; import { AllergenBadges } from "./AllergenBadges"; import { DietBadges } from "./DietBadges"; import { CategoryIcon, IngredientTypeIcon, SubcategoryIcon } from "./ingredient-icons"; @@ -32,10 +32,12 @@ const ALL = "ALL" as const; * ingredients — a recipe's ingredient list, or a profile's disliked list) * keeps the same one from being added twice. * - * The two toggle buttons trailing the search input show/hide the - * allergen/diet badge rows on every card — a display preference local to - * this picker (not persisted), for whoever finds two rows of badges per - * card too noisy while just browsing/searching by name. + * The settings menu trailing the search input shows/hides the allergen/diet + * badge rows on every card — a display preference local to this picker (not + * persisted), for whoever finds two rows of badges per card too noisy while + * just browsing/searching by name. A labeled checkbox menu rather than two + * bare icon-only toggle buttons — those turned out too ambiguous on their + * own (unclear what each icon meant without a label attached). */ export function IngredientPicker({ ingredients, @@ -57,6 +59,7 @@ export function IngredientPicker({ // badges per card too noisy while just browsing/searching by name. const [showAllergens, setShowAllergens] = useState(true); const [showDiets, setShowDiets] = useState(true); + const [isDisplayMenuOpen, setIsDisplayMenuOpen] = useState(false); function selectCategory(next: IngredientCategory | typeof ALL) { setCategory(next); @@ -90,25 +93,38 @@ export function IngredientPicker({ onChange={(e) => setQuery(e.target.value)} placeholder={t("recipes.form.searchIngredientPlaceholder")} /> -
+
- + {isDisplayMenuOpen && ( +
+ + +
+ )}
diff --git a/apps/web/src/features/recipes/recipes.scss b/apps/web/src/features/recipes/recipes.scss index dcc46a1..e87b36e 100644 --- a/apps/web/src/features/recipes/recipes.scss +++ b/apps/web/src/features/recipes/recipes.scss @@ -726,20 +726,19 @@ } } - // Show/hide toggles for the allergen/diet badge rows on every card below - // — trailing the search input, same "icon button with an active state" - // pattern as `FavoriteStarButton`. - &__search-toggles { - display: flex; + // Settings menu for the allergen/diet badge rows on every card below — + // trailing the search input. A single gear button + labeled checkboxes + // (not two bare icon-only toggles, the earlier design here) — an icon + // alone couldn't say clearly enough which badge row it hid. + &__display-options { + position: relative; flex-shrink: 0; - gap: var(--space-xs); } - &__search-toggle { + &__display-toggle { display: flex; align-items: center; justify-content: center; - flex-shrink: 0; width: 2.25rem; height: 2.25rem; padding: 0; @@ -765,6 +764,31 @@ } } + // Anchored below-right of the toggle — same transient-overlay reasoning + // as `.app-sidebar__account-menu` (AppLayout.scss). + &__display-menu { + position: absolute; + z-index: 10; + top: calc(100% + var(--space-xs)); + right: 0; + display: flex; + flex-direction: column; + gap: var(--space-sm); + padding: var(--space-sm); + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-base); + box-shadow: var(--shadow-md); + + // Box/checkmark look comes from the app-wide "selectable card" rule in + // global.scss (`label:has(> input[type="checkbox"])`) — this only adds + // what's specific to sitting inside a dropdown menu. + label { + font-size: var(--font-size-sm); + white-space: nowrap; + } + } + &__categories { display: flex; gap: var(--space-xs); diff --git a/apps/web/src/layouts/nav-icons.tsx b/apps/web/src/layouts/nav-icons.tsx index 25de06d..90adceb 100644 --- a/apps/web/src/layouts/nav-icons.tsx +++ b/apps/web/src/layouts/nav-icons.tsx @@ -128,14 +128,3 @@ export function PublicIcon() { ); } - -/** Allergens — the show/hide allergen-badges toggle on `IngredientPicker`'s search bar. */ -export function AllergenIcon() { - return ( - - - - - - ); -} diff --git a/apps/web/src/locales/fr/translation.json b/apps/web/src/locales/fr/translation.json index 3598b17..2d0c7f0 100644 --- a/apps/web/src/locales/fr/translation.json +++ b/apps/web/src/locales/fr/translation.json @@ -166,8 +166,9 @@ }, "dietsLabel": "Régime(s) associé(s)", "searchIngredientPlaceholder": "Rechercher un ingrédient…", - "toggleDiets": "Afficher/masquer les régimes alimentaires", - "toggleAllergens": "Afficher/masquer les allergènes", + "displayOptions": "Options d'affichage", + "showDietsLabel": "Régimes alimentaires", + "showAllergensLabel": "Allergènes", "allCategories": "Tout", "allSubcategories": "Tout", "noIngredientFound": "Aucun ingrédient trouvé.",