fix: recipe card badge placement, missing tooltips, untranslated label

- Batch-cook indicator moved from next to the title into the icon row
  alongside favorite/visibility (all three now get a tooltip, matching
  the existing favorite-button pattern).
- Favorite button's tooltip text was hardcoded English ("Save"/
  "Saved") instead of using the translation keys already used for its
  aria-label.
- Shortened the batch-cook generate dialog's "Generating…" label
  (fr.json edited by user) — the long text was the real cause of the
  modal overlap, not the dialog structure.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Arnaud
2026-07-12 10:29:13 +02:00
parent 002f14ced0
commit 1baf5ce20e
3 changed files with 50 additions and 16 deletions
+45 -11
View File
@@ -117,12 +117,9 @@ function GridCard({ recipe, selected, selectMode }: { recipe: Recipe; selected:
> >
<RecipeThumb recipe={recipe} selectMode={selectMode} selected={selected} className="aspect-video" /> <RecipeThumb recipe={recipe} selectMode={selectMode} selected={selected} className="aspect-video" />
<div className="flex flex-col flex-1 p-3 gap-1"> <div className="flex flex-col flex-1 p-3 gap-1">
<div className="flex items-center gap-1.5">
<h3 className={cn("font-semibold leading-tight line-clamp-2 text-sm transition-colors", !selectMode && "group-hover:text-primary")}> <h3 className={cn("font-semibold leading-tight line-clamp-2 text-sm transition-colors", !selectMode && "group-hover:text-primary")}>
{recipe.title} {recipe.title}
</h3> </h3>
{recipe.isBatchCook && <ChefHat className="h-3.5 w-3.5 text-primary shrink-0" />}
</div>
{recipe.description && ( {recipe.description && (
<p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed"> <p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed">
{recipe.isBatchCook ? stripMarkdown(recipe.description) : recipe.description} {recipe.isBatchCook ? stripMarkdown(recipe.description) : recipe.description}
@@ -154,12 +151,25 @@ function GridCard({ recipe, selected, selectMode }: { recipe: Recipe; selected:
)} )}
</div> </div>
<div className="flex items-center gap-1 shrink-0"> <div className="flex items-center gap-1 shrink-0">
{recipe.isBatchCook && (
<TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="p-1.5 inline-flex"><ChefHat className="h-3.5 w-3.5 text-primary" /></span>} />
<TooltipContent>{t("batchCookBadge")}</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{!selectMode && ( {!selectMode && (
<StopPropagation> <StopPropagation>
<FavoriteButton recipeId={recipe.id} initialFavorited={recipe.isFavorited} /> <FavoriteButton recipeId={recipe.id} initialFavorited={recipe.isFavorited} />
</StopPropagation> </StopPropagation>
)} )}
<VisibilityIcon className="h-3 w-3" /> <TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="p-1.5 inline-flex"><VisibilityIcon className="h-3 w-3" /></span>} />
<TooltipContent>{t(`visibility.${recipe.visibility}`)}</TooltipContent>
</Tooltip>
</TooltipProvider>
</div> </div>
</div> </div>
</div> </div>
@@ -184,17 +194,29 @@ function ListRow({ recipe, selected, selectMode }: { recipe: Recipe; selected: b
<RecipeThumb recipe={recipe} selectMode={selectMode} selected={selected} className="w-28 h-20 rounded-lg" /> <RecipeThumb recipe={recipe} selectMode={selectMode} selected={selected} className="w-28 h-20 rounded-lg" />
<div className="flex-1 min-w-0 flex flex-col gap-1"> <div className="flex-1 min-w-0 flex flex-col gap-1">
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<h3 className={cn("font-semibold leading-tight line-clamp-1 text-sm flex items-center gap-1.5", !selectMode && "group-hover:text-primary")}> <h3 className={cn("font-semibold leading-tight line-clamp-1 text-sm", !selectMode && "group-hover:text-primary")}>
{recipe.title} {recipe.title}
{recipe.isBatchCook && <ChefHat className="h-3.5 w-3.5 text-primary shrink-0" />}
</h3> </h3>
<div className="flex items-center gap-1 shrink-0"> <div className="flex items-center gap-1 shrink-0">
{recipe.isBatchCook && (
<TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="p-1.5 inline-flex"><ChefHat className="h-3.5 w-3.5 text-primary" /></span>} />
<TooltipContent>{t("batchCookBadge")}</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{!selectMode && ( {!selectMode && (
<StopPropagation> <StopPropagation>
<FavoriteButton recipeId={recipe.id} initialFavorited={recipe.isFavorited} /> <FavoriteButton recipeId={recipe.id} initialFavorited={recipe.isFavorited} />
</StopPropagation> </StopPropagation>
)} )}
<VisibilityIcon className="h-3.5 w-3.5 text-muted-foreground" /> <TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="p-1.5 inline-flex"><VisibilityIcon className="h-3.5 w-3.5 text-muted-foreground" /></span>} />
<TooltipContent>{t(`visibility.${recipe.visibility}`)}</TooltipContent>
</Tooltip>
</TooltipProvider>
</div> </div>
</div> </div>
{recipe.description && <p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed">{recipe.isBatchCook ? stripMarkdown(recipe.description) : recipe.description}</p>} {recipe.description && <p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed">{recipe.isBatchCook ? stripMarkdown(recipe.description) : recipe.description}</p>}
@@ -231,9 +253,8 @@ function CompactRow({ recipe, selected, selectMode }: { recipe: Recipe; selected
)} )}
> >
<RecipeThumb recipe={recipe} selectMode={selectMode} selected={selected} className="w-10 h-10 rounded-md shrink-0" /> <RecipeThumb recipe={recipe} selectMode={selectMode} selected={selected} className="w-10 h-10 rounded-md shrink-0" />
<h3 className={cn("font-medium text-sm truncate flex-1 min-w-0 flex items-center gap-1.5", !selectMode && "group-hover:text-primary")}> <h3 className={cn("font-medium text-sm truncate flex-1 min-w-0", !selectMode && "group-hover:text-primary")}>
<span className="truncate">{recipe.title}</span> {recipe.title}
{recipe.isBatchCook && <ChefHat className="h-3.5 w-3.5 text-primary shrink-0" />}
</h3> </h3>
<span className="hidden sm:flex items-center gap-1 text-xs text-muted-foreground shrink-0"><Users className="h-3 w-3" />{recipe.baseServings}</span> <span className="hidden sm:flex items-center gap-1 text-xs text-muted-foreground shrink-0"><Users className="h-3 w-3" />{recipe.baseServings}</span>
{totalMins > 0 && ( {totalMins > 0 && (
@@ -245,12 +266,25 @@ function CompactRow({ recipe, selected, selectMode }: { recipe: Recipe; selected
<span className="hidden md:inline text-xs text-muted-foreground shrink-0 w-16 text-right"> <span className="hidden md:inline text-xs text-muted-foreground shrink-0 w-16 text-right">
{recipe.updatedAt.toLocaleDateString(locale, { month: "short", day: "numeric" })} {recipe.updatedAt.toLocaleDateString(locale, { month: "short", day: "numeric" })}
</span> </span>
{recipe.isBatchCook && (
<TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="p-1.5 inline-flex shrink-0"><ChefHat className="h-3.5 w-3.5 text-primary" /></span>} />
<TooltipContent>{t("batchCookBadge")}</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{!selectMode && ( {!selectMode && (
<StopPropagation> <StopPropagation>
<FavoriteButton recipeId={recipe.id} initialFavorited={recipe.isFavorited} /> <FavoriteButton recipeId={recipe.id} initialFavorited={recipe.isFavorited} />
</StopPropagation> </StopPropagation>
)} )}
<VisibilityIcon className="h-3.5 w-3.5 shrink-0 text-muted-foreground" /> <TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="p-1.5 inline-flex shrink-0"><VisibilityIcon className="h-3.5 w-3.5 text-muted-foreground" /></span>} />
<TooltipContent>{t(`visibility.${recipe.visibility}`)}</TooltipContent>
</Tooltip>
</TooltipProvider>
</div> </div>
); );
} }
@@ -58,7 +58,7 @@ export function FavoriteButton({
<Heart className={cn("h-4 w-4", favorited ? "fill-red-500 text-red-500" : iconClassName)} /> <Heart className={cn("h-4 w-4", favorited ? "fill-red-500 text-red-500" : iconClassName)} />
</Button> </Button>
} /> } />
<TooltipContent>{favorited ? "Saved" : "Save"}</TooltipContent> <TooltipContent>{favorited ? tSocial("favoriteRemove") : tSocial("favoriteAdd")}</TooltipContent>
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>
); );
+1 -1
View File
@@ -553,7 +553,7 @@
"dietaryPrefsPlaceholder": "ex : végétarien, sans crustacés", "dietaryPrefsPlaceholder": "ex : végétarien, sans crustacés",
"anyDifficulty": "Peu importe", "anyDifficulty": "Peu importe",
"generate": "Générer", "generate": "Générer",
"generating": "Génération… ça peut prendre une minute", "generating": "Génération…",
"generateSuccess": "Session de batch cooking créée", "generateSuccess": "Session de batch cooking créée",
"generateFailed": "Échec de la génération" "generateFailed": "Échec de la génération"
}, },