From 0883eb00c0fa9d1f4ee662bdc3e78e9aa70454ca Mon Sep 17 00:00:00 2001 From: Mari Zhevagin Date: Sat, 17 Oct 2026 01:30:35 +0200 Subject: [PATCH 1/4] liten forandring av tekst --- client/src/components/profile/PreferencesForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/profile/PreferencesForm.tsx b/client/src/components/profile/PreferencesForm.tsx index 715bef1..16af25d 100644 --- a/client/src/components/profile/PreferencesForm.tsx +++ b/client/src/components/profile/PreferencesForm.tsx @@ -110,7 +110,7 @@ export function PreferencesForm() { Preferanser

- Brukes til å tilpasse oppskriftene til deg. + Preferansene er ikke i bruk ennå.

@@ -139,7 +139,7 @@ export function PreferencesForm() {
Allergier

- Oppskrifter med disse blir markert. + Oppskrifter med disse blir markert (ikke aktiv ennå).

{ALLERGIES.map((name) => { From 168bbaadf6c5585e5bf3201515c2fdf566d88a52 Mon Sep 17 00:00:00 2001 From: Mari Zhevagin Date: Sat, 17 Oct 2026 15:10:32 +0200 Subject: [PATCH 2/4] animasjoner --- .../components/favorites/FavoriteButton.tsx | 35 +++- .../components/profile/EditProfileDialog.tsx | 61 +++++-- client/src/lib/motion.ts | 2 + client/src/routes/FavoritesPage.tsx | 5 - client/src/routes/ProfilePage.tsx | 153 +++++++++++------- 5 files changed, 177 insertions(+), 79 deletions(-) diff --git a/client/src/components/favorites/FavoriteButton.tsx b/client/src/components/favorites/FavoriteButton.tsx index 018b632..fd37111 100644 --- a/client/src/components/favorites/FavoriteButton.tsx +++ b/client/src/components/favorites/FavoriteButton.tsx @@ -4,6 +4,9 @@ import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder'; import { useCurrentUser } from '../../lib/useCurrentUser'; import { LoginRequiredDialog } from '../layout/LoginRequiredDialog'; import { MY_FAVORITES, TOGGLE_FAVORITE } from '../../graphql/favorites'; +import { useState } from 'react'; +import { motion, AnimatePresence } from 'motion/react'; +import { quick } from '../../lib/motion'; type FavoriteButtonProps = { recipeId: string; @@ -24,6 +27,8 @@ export function FavoriteButton({ recipeId, title }: FavoriteButtonProps) { // henter favorittene på nytt så hjertene og favorittsiden blir riktige refetchQueries: [MY_FAVORITES], }); + // teller trykk så ringen spilles av på nytt hver gang + const [burst, setBurst] = useState(0); // ikke innlogget så hjertet åpner innloggingspopupen if (!user) { @@ -46,20 +51,40 @@ export function FavoriteButton({ recipeId, title }: FavoriteButtonProps) { const isFavorite = data?.myFavorites.some((recipe) => recipe.id === recipeId) ?? false; - return ( - + ); } diff --git a/client/src/components/profile/EditProfileDialog.tsx b/client/src/components/profile/EditProfileDialog.tsx index cd3988b..ef37a3b 100644 --- a/client/src/components/profile/EditProfileDialog.tsx +++ b/client/src/components/profile/EditProfileDialog.tsx @@ -1,11 +1,13 @@ import { useState, type ReactNode, type SubmitEvent } from 'react'; import * as RadixDialog from '@radix-ui/react-dialog'; import { useMutation } from '@apollo/client/react'; +import { AnimatePresence, motion } from 'motion/react'; import { Button } from '../ui/Button'; import { Field } from '../ui/Field'; import { Input } from '../ui/Input'; import { useCurrentUser } from '../../lib/useCurrentUser'; import { CHANGE_PASSWORD, UPDATE_PROFILE } from '../../graphql/auth'; +import { fadeUp, quick } from '../../lib/motion'; // passordet må være minst så mange tegn const MIN_PASSWORD_LENGTH = 6; @@ -54,6 +56,11 @@ export function EditProfileDialog({ trigger }: EditProfileDialogProps) { try { await updateProfile({ variables: { name: name.trim() } }); setNameMessage('Navnet er lagret.'); + // skjuler meldingen etter litt men bare hvis den ikke er byttet ut + setTimeout( + () => setNameMessage((m) => (m === 'Navnet er lagret.' ? '' : m)), + 2500, + ); } catch (error) { setNameMessage( error instanceof Error ? error.message : 'Kunne ikke lagre navnet.', @@ -87,6 +94,12 @@ export function EditProfileDialog({ trigger }: EditProfileDialogProps) { setNewPassword(''); setRepeatPassword(''); setPasswordMessage('Passordet er byttet.'); + // skjuler meldingen etter litt men bare hvis den ikke er byttet ut + setTimeout( + () => + setPasswordMessage((m) => (m === 'Passordet er byttet.' ? '' : m)), + 2500, + ); } catch (error) { setPasswordMessage( error instanceof Error ? error.message : 'Kunne ikke bytte passord.', @@ -101,7 +114,7 @@ export function EditProfileDialog({ trigger }: EditProfileDialogProps) { {/* popup som kan scrolles på små skjermer */} - + Rediger profil @@ -119,11 +132,23 @@ export function EditProfileDialog({ trigger }: EditProfileDialogProps) { autoComplete="name" /> - {nameMessage && ( -

- {nameMessage} -

- )} + {/* meldingen tones inn hver gang teksten endres */} + + {nameMessage && ( + + {nameMessage} + + )} + ))}
- + {/* preferanser på mobil bare når fanen er valgt */}
setActiveTab(tab)} - className={`-mb-px cursor-pointer border-b-2 pb-2 font-display text-2xl transition-colors ${FOCUS_RING} ${ - desktopTab === tab - ? 'border-primary text-primary' - : 'border-transparent hover:text-primary' + className={`relative cursor-pointer pb-2 font-display text-2xl transition-colors ${FOCUS_RING} ${ + desktopTab === tab ? 'text-primary' : 'hover:text-primary' }`} > {RECIPE_TABS[tab].label} + {/* streken glir til fanen som er valgt */} + {desktopTab === tab && ( + + )} ))}
@@ -256,19 +272,29 @@ export default function ProfilePage() { {/* søppelbøtte som slår på valg av egne oppskrifter */} {desktopTab === 'shared' && myRecipes.length > 0 && (
- {isSelecting && ( - <> - - {selectedIds.length} valgt - - - selectedIds.includes(recipe.id), - )} - onDeleted={toggleSelecting} - /> - - )} + {/* teksten og slett knappen vokser ut fra søppelbøtta */} + + {isSelecting && ( + + + {selectedIds.length} valgt + + + selectedIds.includes(recipe.id), + )} + onDeleted={toggleSelecting} + /> + + )} + - ) : ( -
- -
- )} - - ))} - + // key gjør at listen tones inn på nytt når fanen byttes + + {/* kort som fjernes tones ut og resten glir på plass */} + + {tabRecipes.map((recipe) => ( + + + {isSelecting && ( + // dekker kortet så trykk velger i stedet for å åpne oppskriften + + )} + + ))} + + ) : (

{RECIPE_TABS[desktopTab].empty}

From 27d2e17d06f010afe55b4efe49217dfac7b4948c Mon Sep 17 00:00:00 2001 From: Mari Zhevagin Date: Sat, 17 Oct 2026 15:24:43 +0200 Subject: [PATCH 3/4] la till noe animasjon i index --- client/src/index.css | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/client/src/index.css b/client/src/index.css index 0c3e02a..46007b1 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -33,6 +33,36 @@ /* bredde der pc header tar over fra mobil header */ --breakpoint-desktop: 35rem; + + + /* popup tones inn og glir inn */ + --animate-dialog-in: dialog-in 200ms ease-out; + --animate-dialog-out: dialog-out 150ms ease-in; + --animate-overlay-in: overlay-in 200ms ease-out; + --animate-overlay-out: overlay-out 150ms ease-in; + + @keyframes dialog-in { + from { + opacity: 0; + transform: translateY(12px); + } + } + @keyframes dialog-out { + to { + opacity: 0; + transform: translateY(12px); + } + } + @keyframes overlay-in { + from { + opacity: 0; + } + } + @keyframes overlay-out { + to { + opacity: 0; + } + } } /* Grunnleggende styling */ From e102bc0ca0e9cb76df94ddb822893a54635129e7 Mon Sep 17 00:00:00 2001 From: Mari Zhevagin Date: Sat, 17 Oct 2026 15:46:50 +0200 Subject: [PATCH 4/4] =?UTF-8?q?animasjon=20p=C3=A5=20popupene?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/favorites/FavoriteButton.tsx | 4 ++-- client/src/components/layout/LoginRequiredDialog.tsx | 4 ++-- client/src/components/profile/DeleteRecipesDialog.tsx | 4 ++-- client/src/components/profile/EditProfileDialog.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/components/favorites/FavoriteButton.tsx b/client/src/components/favorites/FavoriteButton.tsx index fd37111..2e52459 100644 --- a/client/src/components/favorites/FavoriteButton.tsx +++ b/client/src/components/favorites/FavoriteButton.tsx @@ -51,7 +51,7 @@ export function FavoriteButton({ recipeId, title }: FavoriteButtonProps) { const isFavorite = data?.myFavorites.some((recipe) => recipe.id === recipeId) ?? false; - return ( + return ( - {/* egen AnimatePresence så ringen alltid animeres også inne i lister */} + {/* egen AnimatePresence så ringen alltid animeres også inne i lister */} {burst > 0 && ( {trigger} - + {/* popup */} - + Du må logge inn for å bruke dette diff --git a/client/src/components/profile/DeleteRecipesDialog.tsx b/client/src/components/profile/DeleteRecipesDialog.tsx index 7a9da18..7acf6e9 100644 --- a/client/src/components/profile/DeleteRecipesDialog.tsx +++ b/client/src/components/profile/DeleteRecipesDialog.tsx @@ -55,8 +55,8 @@ export function DeleteRecipesDialog({ - - + + {count === 1 ? 'Vil du slette 1 oppskrift?' diff --git a/client/src/components/profile/EditProfileDialog.tsx b/client/src/components/profile/EditProfileDialog.tsx index ef37a3b..405c74f 100644 --- a/client/src/components/profile/EditProfileDialog.tsx +++ b/client/src/components/profile/EditProfileDialog.tsx @@ -111,9 +111,9 @@ export function EditProfileDialog({ trigger }: EditProfileDialogProps) { {trigger} - + {/* popup som kan scrolles på små skjermer */} - + Rediger profil