diff --git a/frontend/src/App.css b/frontend/src/App.css
index 4ba5a12..06b80ca 100644
--- a/frontend/src/App.css
+++ b/frontend/src/App.css
@@ -107,8 +107,8 @@
.ingredient-group-card {
@apply py-4 border-b border-gray-400;
}
-
- .enumeration-indicator {
+
+ .circular-container {
@apply flex-shrink-0 w-7 h-7 rounded-full bg-blue-300 text-white flex items-center justify-center shadow-sm;
}
diff --git a/frontend/src/components/basics/NumberStepControl.tsx b/frontend/src/components/basics/NumberStepControl.tsx
new file mode 100644
index 0000000..67b56fb
--- /dev/null
+++ b/frontend/src/components/basics/NumberStepControl.tsx
@@ -0,0 +1,74 @@
+import {Minus, Plus} from "lucide-react";
+import {defaultIconSize} from "./SvgIcon.tsx";
+
+type NumberStepControlProps = {
+ /** Current numeric value */
+ value: number;
+ /** Callback when value changes */
+ onChange: (newValue: number) => void;
+ /** Optional: minimum allowed value */
+ min?: number;
+ /** Optional: maximum allowed value */
+ max?: number;
+ /** Optional: step increment (default = 1) */
+ step?: number;
+ /** Optional: additional Tailwind classes */
+ className?: string;
+};
+
+/**
+ * A compact number input with +/– buttons.
+ * Removes native browser spinners and supports min/max limits.
+ */
+export function NumberStepControl({
+ value,
+ onChange,
+ min = Number.NEGATIVE_INFINITY,
+ max = Number.POSITIVE_INFINITY,
+ step = 1,
+ className = "",
+ }: NumberStepControlProps) {
+ const handleDecrease = () => {
+ const newValue = Math.max(value - step, min);
+ onChange(newValue);
+ };
+
+ const handleIncrease = () => {
+ const newValue = Math.min(value + step, max);
+ onChange(newValue);
+ };
+
+ const handleInputChange = (e: React.ChangeEvent) => {
+ const num = Number(e.target.value);
+ if (!isNaN(num)) onChange(Math.min(Math.max(num, min), max));
+ };
+
+ return (
+
+ );
+}
diff --git a/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx b/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx
index 37f953b..aff0952 100644
--- a/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx
+++ b/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx
@@ -2,64 +2,64 @@
* Single step component for Desktop editor with drag-and-drop support.
*/
-import { useSortable } from "@dnd-kit/sortable";
-import { CSS } from "@dnd-kit/utilities";
-import type { InstructionStepModel } from "../../models/InstructionStepModel";
+import {useSortable} from "@dnd-kit/sortable";
+import {CSS} from "@dnd-kit/utilities";
+import type {InstructionStepModel} from "../../models/InstructionStepModel";
import Button from "../basics/Button";
-import { X } from "lucide-react"
-import { ButtonType } from "../basics/BasicButtonDefinitions";
+import {X} from "lucide-react"
+import {ButtonType} from "../basics/BasicButtonDefinitions";
type InstructionStepDesktopListItemProps = {
- id: string | number;
- index: number;
- step: InstructionStepModel;
- onUpdate: (index: number, value: string) => void;
- onRemove: (index: number) => void;
+ id: string | number;
+ index: number;
+ step: InstructionStepModel;
+ onUpdate: (index: number, value: string) => void;
+ onRemove: (index: number) => void;
};
export function InstructionStepDesktopListItem({
- id,
- index,
- step,
- onUpdate,
- onRemove,
-}: InstructionStepDesktopListItemProps) {
- const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
+ id,
+ index,
+ step,
+ onUpdate,
+ onRemove,
+ }: InstructionStepDesktopListItemProps) {
+ const {attributes, listeners, setNodeRef, transform, transition} = useSortable({id});
- const style = { transform: CSS.Transform.toString(transform), transition };
+ const style = {transform: CSS.Transform.toString(transform), transition};
- return (
-
-
- {index + 1}
-
+ return (
+
- );
+
+ );
}
diff --git a/frontend/src/components/recipes/RecipeDetailPage.tsx b/frontend/src/components/recipes/RecipeDetailPage.tsx
index a1fcfbf..29fa081 100644
--- a/frontend/src/components/recipes/RecipeDetailPage.tsx
+++ b/frontend/src/components/recipes/RecipeDetailPage.tsx
@@ -5,6 +5,7 @@ import {fetchRecipe} from "../../api/points/RecipePoint"
import {getRecipeEditUrl, getRecipeListUrl} from "../../routes"
import ButtonLink from "../basics/ButtonLink"
import {mapRecipeDtoToModel} from "../../mappers/RecipeMapper"
+import {NumberStepControl} from "../basics/NumberStepControl.tsx";
/**
@@ -99,36 +100,12 @@ export default function RecipeDetailPage() {
Für {recipeWorkingCopy.servings.amount} {recipeWorkingCopy.servings.unit}
-
- {/* Minus button */}
-
-
- {/* Number input (no spin buttons) */}
- recalculateIngredients(Number(e.target.value))}
- min={1}
- />
-
- {/* Plus button */}
-
-
+
{/* Ingredients */}
@@ -156,7 +133,7 @@ export default function RecipeDetailPage() {
{recipe.instructionStepList.map((step, j) => (
{/* Step number circle */}
-