From 3f075d509b94197ba584a5c5bbc12e3e1f80aa7c Mon Sep 17 00:00:00 2001 From: Anika Raemer Date: Sun, 12 Oct 2025 17:17:21 +0200 Subject: [PATCH] refactor icons. Somehow button colors are no longer working... --- frontend/src/App.css | 34 ++++---- frontend/src/components/LoginPage.tsx | 7 +- .../basics/BasicButtonDefinitions.ts | 35 ++++++++ frontend/src/components/basics/Button.tsx | 80 +++++++------------ frontend/src/components/basics/ButtonLink.tsx | 20 +++-- .../src/components/basics/PasswordField.tsx | 5 +- .../src/components/basics/SearchField.tsx | 17 ++-- frontend/src/components/basics/SvgIcon.tsx | 1 + .../recipes/IngredientGroupListEditor.tsx | 7 +- .../recipes/IngredientListEditor.tsx | 9 ++- .../InstructionStepDesktopListItem.tsx | 8 +- .../InstructionStepListDesktopEditor.tsx | 11 +-- .../recipes/InstructionStepListEditor.tsx | 2 +- .../InstructionStepListMobileEditor.tsx | 17 ++-- .../src/components/recipes/RecipeEditor.tsx | 7 +- .../components/recipes/RecipeListToolbar.tsx | 2 +- 16 files changed, 152 insertions(+), 110 deletions(-) create mode 100644 frontend/src/components/basics/BasicButtonDefinitions.ts diff --git a/frontend/src/App.css b/frontend/src/App.css index 1b3fd1b..3149ef6 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -7,7 +7,7 @@ /* background */ .app-bg { - @apply flex items-center w-screen justify-center min-h-screen bg-gray-50 + @apply flex items-center w-screen justify-center min-h-screen bg-gray-50; } /* headings */ @@ -23,49 +23,55 @@ @apply font-semibold mb-2 mt-4; } + /* icons */ + .default-icon { + @apply text-gray-400 hover:text-gray-500; + } + + /* labels */ .label { - @apply text-gray-600 + @apply text-gray-600; } /* errors */ .error-text { - @apply text-sm text-red-600 + @apply text-sm text-red-600; } /* buttons */ .basic-button{ - @apply px-4 py-2 shadow-md rounded-lg whitespace-nowrap + @apply px-4 py-2 shadow-md rounded-lg whitespace-nowrap; } .default-button-bg { - @apply bg-gray-300 hover:bg-gray-400 + @apply bg-gray-300 hover:bg-gray-400; } .default-button-text{ - @apply text-gray-600 + @apply text-gray-600; } .primary-button-bg { - @apply bg-blue-300 hover:bg-blue-400 + @apply bg-blue-300 hover:bg-blue-400; } .primary-button-text { - @apply text-gray-600 + @apply text-gray-600; } .dark-button-bg{ - @apply bg-gray-600 hover:bg-gray-800 + @apply bg-gray-600 hover:bg-gray-800; } .dark-button-text{ - @apply text-white + @apply text-white; } .transparent-button-bg { - @apply bg-transparent hover:bg-transparent + @apply bg-transparent hover:bg-transparent; } .transparent-button-text { - @apply text-gray-600 + @apply text-gray-600; } /* input fields like input and textarea */ .input-field { - @apply p-2 w-full border rounded-md placeholder-gray-400 border-gray-600 hover:border-blue-600 transition-colors text-gray-600 focus:outline-none focus:border-blue-800; + @apply p-2 w-full border rounded-md placeholder-gray-400 border-gray-600 hover:border-blue-800 transition-colors text-gray-600 focus:outline-none focus:border-blue-900; } /* groups */ @@ -87,7 +93,7 @@ } .enumeration-indicator{ - @apply flex-shrink-0 w-7 h-7 rounded-full bg-blue-300 text-white flex items-center justify-center shadow-sm + @apply flex-shrink-0 w-7 h-7 rounded-full bg-blue-300 text-white flex items-center justify-center shadow-sm; } } \ No newline at end of file diff --git a/frontend/src/components/LoginPage.tsx b/frontend/src/components/LoginPage.tsx index d52c5ca..ffd6c74 100644 --- a/frontend/src/components/LoginPage.tsx +++ b/frontend/src/components/LoginPage.tsx @@ -1,11 +1,12 @@ import { useState } from "react"; -import Button, { ButtonType } from "./basics/Button"; +import Button from "./basics/Button"; import type { LoginRequestDto } from "../api/dtos/LoginRequestDto"; import type { LoginResponseDto } from "../api/dtos/LoginResponseDto"; import { login } from "../api/points/AuthPoint"; import { getRecipeListUrl } from "../routes"; import { useNavigate } from "react-router-dom"; import PasswordField from "./basics/PasswordField"; +import { ButtonType } from "./basics/BasicButtonDefinitions"; export default function LoginPage() { const [userName, setUserName] = useState(""); @@ -14,6 +15,9 @@ export default function LoginPage() { const navigate = useNavigate(); + /** + * Login + */ const executeLogin = async () => { const dto: LoginRequestDto = { userName, @@ -26,6 +30,7 @@ export default function LoginPage() { localStorage.setItem("session", JSON.stringify(loginResponse)); console.log("Successfully logged in as " + loginResponse.userData?.userName); setErrorMessage(null); + // navigate to recipe list after successful login navigate(getRecipeListUrl()); } catch (err: any) { console.error("Login failed:", err); diff --git a/frontend/src/components/basics/BasicButtonDefinitions.ts b/frontend/src/components/basics/BasicButtonDefinitions.ts new file mode 100644 index 0000000..04c1769 --- /dev/null +++ b/frontend/src/components/basics/BasicButtonDefinitions.ts @@ -0,0 +1,35 @@ +import type { LucideIcon } from "lucide-react"; + +export type BasicButtonProps = { + /** Optional Lucide icon (e.g. Plus, X, Check) */ + icon?: LucideIcon; + text?: string; + buttonType?: ButtonType; + /** Optional additional style */ + className?: string; +} + +/** + * Define button types here. + * Export as enum like class. + */ +export const ButtonType = { + DarkButton: { + textColor: "text-dark-button-text", + backgroundColor: "bg-dark-button-bg", + }, + PrimaryButton: { + textColor: "text-primary-button-text", + backgroundColor: "bg-primary-button-bg", + }, + DefaultButton: { + textColor: "text-default-button-text", + backgroundColor: "bg-default-button-bg", + }, + TransparentButton: { + textColor: "text-transparent-button-text", + backgroundColor: "bg-transparent-button-bg", + }, +} as const; + +export type ButtonType = typeof ButtonType[keyof typeof ButtonType]; \ No newline at end of file diff --git a/frontend/src/components/basics/Button.tsx b/frontend/src/components/basics/Button.tsx index 2423833..5506e76 100644 --- a/frontend/src/components/basics/Button.tsx +++ b/frontend/src/components/basics/Button.tsx @@ -1,52 +1,32 @@ -import SvgIcon, { Icon } from "./SvgIcon" +import { defaultIconSize } from "./SvgIcon"; +import { ButtonType, type BasicButtonProps } from "./BasicButtonDefinitions"; -type ButtonProps = { - onClick: () => void, - icon?: Icon, - text?: string, - buttonType?: ButtonType - className?: string +type ButtonProps = BasicButtonProps & { + onClick: () => void; +}; + +export default function Button({ + onClick, + icon: Icon, + text, + buttonType = ButtonType.DefaultButton, + className = "", + ...props +}: ButtonProps) { + return ( + + ); } - -export const ButtonType = { - DarkButton: { - textColor: "dark-button-text", - backgroundColor: "dark-button-bg" - }, - PrimaryButton: { - textColor: "primary-button-text", - backgroundColor: "primary-button-bg" - }, - DefaultButton: { - textColor: "default-button-text", - backgroundColor: "default-button-bg" - }, - TransparentButton: { - textColor: "transparent-button-text", - backgroundColor: "transparent-button-bg" - } -} as const; - -export type ButtonType = typeof ButtonType[keyof typeof ButtonType]; - -export default function Button( - { - onClick: onClick, - icon, text, - buttonType = ButtonType.DefaultButton, - className = "" - }: ButtonProps) { - return ( - - ) -} \ No newline at end of file diff --git a/frontend/src/components/basics/ButtonLink.tsx b/frontend/src/components/basics/ButtonLink.tsx index 6ed591f..8256f2a 100644 --- a/frontend/src/components/basics/ButtonLink.tsx +++ b/frontend/src/components/basics/ButtonLink.tsx @@ -1,10 +1,10 @@ import { Link, type LinkProps } from "react-router-dom" -import { ButtonType } from "./Button" +import { defaultIconSize } from "./SvgIcon" +import { ButtonType, type BasicButtonProps } from "./BasicButtonDefinitions" -type ButtonLinkProps = LinkProps & { - text: string - buttonType?: ButtonType - className?: string +type ButtonLinkProps = LinkProps & BasicButtonProps +& { + to: string } /** @@ -13,6 +13,7 @@ type ButtonLinkProps = LinkProps & { export default function ButtonLink({ to, text, + icon: Icon, buttonType = ButtonType.DefaultButton, className = "", ...props @@ -23,7 +24,14 @@ export default function ButtonLink({ className={`basic-button ${buttonType.backgroundColor} ${buttonType.textColor} ${className}`} {...props} > - {text} +
+ {Icon && ( + + )} + {text} +
) } diff --git a/frontend/src/components/basics/PasswordField.tsx b/frontend/src/components/basics/PasswordField.tsx index 2a8ba51..ce78cba 100644 --- a/frontend/src/components/basics/PasswordField.tsx +++ b/frontend/src/components/basics/PasswordField.tsx @@ -1,5 +1,6 @@ import { Eye, EyeOff } from "lucide-react"; import { useState } from "react"; +import { defaultIconSize } from "./SvgIcon"; type PasswordFieldProps = { onPasswordChanged: (password : string) => void @@ -12,7 +13,6 @@ type PasswordFieldProps = { export default function PasswordField({onPasswordChanged, onKeyDown} : PasswordFieldProps){ const [showPassword, setShowPassword] = useState(false); const [password, setPassword] = useState(""); - const iconSize = 20; const changePassword = (password : string) => { setPassword(password); @@ -28,13 +28,14 @@ export default function PasswordField({onPasswordChanged, onKeyDown} : PasswordF onChange={(e) => changePassword(e.target.value)} onKeyDown={onKeyDown} /> + {/* Add a little eye icon to the right for showing password */} ); diff --git a/frontend/src/components/basics/SearchField.tsx b/frontend/src/components/basics/SearchField.tsx index 5221870..d344d63 100644 --- a/frontend/src/components/basics/SearchField.tsx +++ b/frontend/src/components/basics/SearchField.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; -import SvgIcon, { Icon } from "./SvgIcon" +import { Search, X} from "lucide-react"; +import { defaultIconSize } from "./SvgIcon"; /** * Custom search field component including a clear search functionality */ @@ -24,7 +25,7 @@ export default function SearchField({onSearchStringChanged} : SearchFieldProps){
{/* Input of searchfield Defines border and behavior. Requires extra padding at both sides to - accomodate the icons + accommodate the icons */} changeSearchString("") } > - {/* Left icon: Looking glass */} -
- +
diff --git a/frontend/src/components/basics/SvgIcon.tsx b/frontend/src/components/basics/SvgIcon.tsx index 2d88c16..6859a28 100644 --- a/frontend/src/components/basics/SvgIcon.tsx +++ b/frontend/src/components/basics/SvgIcon.tsx @@ -3,6 +3,7 @@ * @todo replace by lucid react */ +export const defaultIconSize = 20; /** * Enum-like const object+type definition to define icons. * The string corresponds to the path definition of the icon diff --git a/frontend/src/components/recipes/IngredientGroupListEditor.tsx b/frontend/src/components/recipes/IngredientGroupListEditor.tsx index 778dd1f..0b40de1 100644 --- a/frontend/src/components/recipes/IngredientGroupListEditor.tsx +++ b/frontend/src/components/recipes/IngredientGroupListEditor.tsx @@ -4,9 +4,10 @@ import type { IngredientModel } from "../../models/IngredientModel" import type { IngredientGroupModel } from "../../models/IngredientGroupModel" -import Button, { ButtonType } from "../basics/Button" -import SvgIcon, { Icon } from "../basics/SvgIcon" +import Button from "../basics/Button" import { IngredientListEditor } from "./IngredientListEditor" +import { Plus } from "lucide-react" +import { ButtonType } from "../basics/BasicButtonDefinitions" type IngredientGroupListEditorProps = { ingredientGroupList: IngredientGroupModel[] @@ -58,7 +59,7 @@ export function IngredientGroupListEditor({ ingredientGroupList, onChange }: Ing ))}