fix: cramped ingredient/step rows on mobile in recipe editor
Both rows packed 4+ inline fields (grip handle, quantity, unit, name, note for ingredients; step number, textarea, timer, delete for steps) into a single flex row with no mobile-aware wrap plan — flex-wrap on ingredients caused the delete button to float disconnected from its row, and steps had no wrap at all, squeezing the textarea down to a sliver. Both now split into two grouped rows below sm: breakpoint (core fields, then secondary field + delete) and collapse back to one row on larger screens. Not visually verified in a browser — this sandbox has no DB/dev server running (Docker unavailable), so this is typecheck+lint verified only. v0.46.2
This commit is contained in:
@@ -2,6 +2,11 @@
|
||||
|
||||
All notable changes to Epicure are documented here. This file is mirrored in-app at `/changelog` (and in the admin dashboard) via `apps/web/lib/changelog.ts` — update both together.
|
||||
|
||||
## 0.46.2 — 2026-07-17 19:20
|
||||
|
||||
### Fixed
|
||||
- Recipe editor's ingredient and step rows were cramped on mobile — 4 inline fields plus a timer/delete button squeezed into one row with no real wrap plan. Both now stack sanely on narrow screens (name/quantity/unit on one line, note/timer + delete on the next) and stay a single row on larger screens.
|
||||
|
||||
## 0.46.1 — 2026-07-17 19:05
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -691,13 +691,14 @@ export function RecipeForm({ recipeId, defaultValues }: RecipeFormProps) {
|
||||
<Label>{t("ingredients")}</Label>
|
||||
<div className="space-y-2">
|
||||
{ingredients.map((ing, i) => (
|
||||
<div key={ing.id} className="flex flex-wrap gap-2 items-start">
|
||||
<div key={ing.id} className="flex flex-col sm:flex-row gap-2 sm:items-start">
|
||||
<div className="flex gap-2 items-start">
|
||||
<GripVertical className="h-4 w-4 text-muted-foreground mt-2 cursor-grab shrink-0" />
|
||||
<Input
|
||||
value={ing.quantity}
|
||||
onChange={(e) => updateIngredient(i, { quantity: e.target.value })}
|
||||
placeholder={t("amount")}
|
||||
className="w-14 sm:w-16 shrink-0"
|
||||
className="w-16 shrink-0"
|
||||
/>
|
||||
<Input
|
||||
value={ing.unit}
|
||||
@@ -709,23 +710,26 @@ export function RecipeForm({ recipeId, defaultValues }: RecipeFormProps) {
|
||||
value={ing.rawName}
|
||||
onChange={(e) => updateIngredient(i, { rawName: e.target.value })}
|
||||
placeholder={t("ingredient")}
|
||||
className="flex-1 min-w-[100px]"
|
||||
className="flex-1 min-w-0"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 items-start pl-6 sm:pl-0">
|
||||
<Input
|
||||
value={ing.note}
|
||||
onChange={(e) => updateIngredient(i, { note: e.target.value })}
|
||||
placeholder={t("note")}
|
||||
className="w-full sm:w-48 sm:shrink-0"
|
||||
className="flex-1 sm:w-48 sm:shrink-0"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => removeIngredient(i)}
|
||||
disabled={ingredients.length === 1}
|
||||
className="mt-1.5 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-30"
|
||||
className="mt-2 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-30 shrink-0"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
@@ -835,7 +839,8 @@ export function RecipeForm({ recipeId, defaultValues }: RecipeFormProps) {
|
||||
<div className="space-y-3">
|
||||
{steps.map((step, i) => (
|
||||
<div key={step.id} className="space-y-1.5">
|
||||
<div className="flex gap-3 items-start">
|
||||
<div className="flex flex-col sm:flex-row gap-2 sm:gap-3">
|
||||
<div className="flex gap-3 flex-1 min-w-0">
|
||||
<div className="mt-2.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-muted text-xs font-bold text-muted-foreground">
|
||||
{i + 1}
|
||||
</div>
|
||||
@@ -846,6 +851,8 @@ export function RecipeForm({ recipeId, defaultValues }: RecipeFormProps) {
|
||||
rows={2}
|
||||
className="flex-1 min-w-0"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 items-start pl-9 sm:pl-0">
|
||||
<Input
|
||||
value={step.timerSeconds}
|
||||
onChange={(e) => updateStep(i, { timerSeconds: e.target.value })}
|
||||
@@ -858,11 +865,12 @@ export function RecipeForm({ recipeId, defaultValues }: RecipeFormProps) {
|
||||
type="button"
|
||||
onClick={() => removeStep(i)}
|
||||
disabled={steps.length === 1}
|
||||
className="mt-2.5 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-30"
|
||||
className="mt-2 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-30 shrink-0"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{isBatchCook && dishes.some((d) => d.name.trim()) && (
|
||||
<div className="flex flex-wrap gap-1.5 pl-9">
|
||||
<span className="text-xs text-muted-foreground self-center">{t("appliesTo")}:</span>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Mirrors CHANGELOG.md at the repo root — update both together.
|
||||
export const APP_VERSION = "0.46.1";
|
||||
export const APP_VERSION = "0.46.2";
|
||||
|
||||
export type ChangelogEntry = {
|
||||
version: string;
|
||||
@@ -11,6 +11,13 @@ export type ChangelogEntry = {
|
||||
};
|
||||
|
||||
export const CHANGELOG: ChangelogEntry[] = [
|
||||
{
|
||||
version: "0.46.2",
|
||||
date: "2026-07-17 19:20",
|
||||
fixed: [
|
||||
"Recipe editor's ingredient and step rows were cramped on mobile — 4 inline fields plus a timer/delete button squeezed into one row with no real wrap plan. Both now stack sanely on narrow screens (name/quantity/unit on one line, note/timer + delete on the next) and stay a single row on larger screens.",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "0.46.1",
|
||||
date: "2026-07-17 19:05",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@epicure/web",
|
||||
"version": "0.46.1",
|
||||
"version": "0.46.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "epicure",
|
||||
"version": "0.46.1",
|
||||
"version": "0.46.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "pnpm --filter web dev",
|
||||
|
||||
Reference in New Issue
Block a user