diff --git a/client/package.json b/client/package.json
index e08860e..a7344b5 100644
--- a/client/package.json
+++ b/client/package.json
@@ -13,6 +13,8 @@
"@apollo/client": "^4.3.1",
"@radix-ui/react-dialog": "^1.1.23",
"@tailwindcss/vite": "^4.3.3",
+ "embla-carousel-autoplay": "^8.6.0",
+ "embla-carousel-react": "^8.6.0",
"graphql": "^16.11.0",
"react": "^19.2.8",
"react-dom": "^19.2.8",
diff --git a/client/src/components/slideshow/RecipeSlideshow.tsx b/client/src/components/slideshow/RecipeSlideshow.tsx
new file mode 100644
index 0000000..1402791
--- /dev/null
+++ b/client/src/components/slideshow/RecipeSlideshow.tsx
@@ -0,0 +1,105 @@
+import type { Recipe } from '../../types/recipe';
+import useEmblaCarousel from 'embla-carousel-react';
+import { Link } from 'react-router';
+import { useEffect, useState } from 'react';
+
+// Fargetemaer for slidesene. panel er tekstboksen, button er knappen for å se en oppskrift
+type SlideshowTheme = 'light' | 'dark' | 'rose';
+
+const themes = {
+ light: { panel: 'bg-secondary/50 text-olive-dark', button: 'bg-olive-dark text-background', dot: 'border-olive-dark', dotActive: 'bg-olive-dark' },
+ dark: { panel: 'bg-olive-dark text-background', button: 'bg-pink-light text-olive-dark', dot: 'border-background', dotActive: 'bg-background' },
+ rose: { panel: 'bg-pink text-pink-light', button: 'bg-primary-hover text-pink-light', dot: 'border-background', dotActive: 'bg-background' },
+}
+
+type RecipeSlideshowProps = {
+ recipes: Recipe[];
+ reversed?: boolean; // Denne er valgfri, og gjør at karusellen i midten er speilvendt
+ theme?: SlideshowTheme;
+};
+
+// Slideshow på forsiden som viser én oppskrift av gangen.
+// Det er mulig å bla med piler, prikkene, sveiping eller med tastaturet.
+export function RecipeSlideshow({ recipes, reversed = false, theme = 'light' }: RecipeSlideshowProps) {
+ // emblaRef kobler Embla opp til vinduet, også brukes emblaAPI til å styre slideshowet.
+ const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true });
+ // Husker hvilken av sidene i slideshowet som vises, sånn at riktig prikk blir farget inn.
+ const [selectedIndex, setSelectedIndex] = useState(0);
+
+ const colors = themes[theme];
+
+ // Oppdaterer selectedIndex hver gang det byttes hvilken side som vises.
+ useEffect(() => {
+ if(!emblaApi) return;
+ const onSelect = () => setSelectedIndex(emblaApi.selectedScrollSnap());
+ emblaApi.on('select', onSelect);
+
+ // Slutter å lytte når slideshowet fjernes fra siden, sånn at det ikke blir minnelekkasjer.
+ return () => {
+ emblaApi.off('select', onSelect);
+ };
+ }, [emblaApi]);
+
+ return (
+ {recipe.description} {recipe.prepTime} min {recipe.portions} porsjoner
+
{recipe.title}
+