From d515342465f1cfcda9ed6145860f491902270fad Mon Sep 17 00:00:00 2001 From: Clemens Beese Date: Tue, 20 Oct 2026 18:11:32 +0200 Subject: [PATCH 1/6] =?UTF-8?q?feat(frontend):=20X-knapp=20som=20t=C3=B8mm?= =?UTF-8?q?er=20s=C3=B8ket=20og=20viser=20standardlista?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/GameSearch/GameSearch.tsx | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/GameSearch/GameSearch.tsx b/frontend/src/components/GameSearch/GameSearch.tsx index d753ebf..74fbeda 100644 --- a/frontend/src/components/GameSearch/GameSearch.tsx +++ b/frontend/src/components/GameSearch/GameSearch.tsx @@ -1,7 +1,8 @@ -import { useId, useState, type KeyboardEvent } from 'react'; +import { useId, useRef, useState, type KeyboardEvent } from 'react'; import { useQuery } from '@apollo/client/react'; import { useDebounce } from '../../hooks/useDebounce'; import { SEARCH_SUGGESTIONS, type Suggestion } from '../../graphql/searchSuggestions'; + import './GameSearch.css'; // Kortere tekst enn dette gir for mange tilfeldige treff, så vi spør ikke serveren @@ -29,6 +30,7 @@ export function GameSearch({ onSearch, onSelectGame }: GameSearchProps) { const [active, setActive] = useState(-1); // markert forslag, -1 = ingen const id = useId(); const listId = `${id}-list`; + const inputRef = useRef(null); // Spør først 300 ms etter siste tastetrykk, og ikke ved for kort tekst const term = useDebounce(input.trim(), 300); @@ -39,7 +41,10 @@ export function GameSearch({ onSearch, onSelectGame }: GameSearchProps) { // Viser forrige svar mens det nye lastes, så lista ikke blinker const suggestions = (data ?? previousData)?.games.edges.map((e) => e.node) ?? []; - const showPopup = open && term.length >= MIN_CHARS; + + // Sjekker også det som står i feltet nå, ikke bare den forsinkede teksten. + // Ellers dukker gamle forslag opp et øyeblikk etter at feltet er tømt. + const showPopup = open && input.trim().length >= MIN_CHARS && term.length >= MIN_CHARS; function select(game: Suggestion) { setOpen(false); @@ -47,6 +52,15 @@ export function GameSearch({ onSearch, onSelectGame }: GameSearchProps) { onSelectGame(game); } + // X-knappen: tømmer feltet og viser standardlista (forsiden) + function clear() { + setInput(''); + setOpen(false); + setActive(-1); + onSearch(''); // App tømmer søket, og fra en detaljside går den til forsiden + inputRef.current?.focus(); // fokus blir i feltet, ellers forsvinner det med knappen + } + function handleKeyDown(e: KeyboardEvent) { if (e.key === 'ArrowDown') { e.preventDefault(); @@ -100,6 +114,13 @@ export function GameSearch({ onSearch, onSelectGame }: GameSearchProps) { onBlur={() => setOpen(false)} /> + {/* Vises bare når det står noe i feltet. aria-label fordi "×" alene ikke sier noe */} + {input && ( + + )} + {showPopup && (
{suggestions.length > 0 ? ( From a696e7d65d1f86450b4e3e7886d4d556ec0c2322 Mon Sep 17 00:00:00 2001 From: Clemens Beese Date: Tue, 20 Oct 2026 18:11:32 +0200 Subject: [PATCH 2/6] =?UTF-8?q?style(frontend):=20X-knapp=20til=20h=C3=B8y?= =?UTF-8?q?re=20i=20s=C3=B8kefeltet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/GameSearch/GameSearch.css | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/GameSearch/GameSearch.css b/frontend/src/components/GameSearch/GameSearch.css index f66f023..c387eae 100644 --- a/frontend/src/components/GameSearch/GameSearch.css +++ b/frontend/src/components/GameSearch/GameSearch.css @@ -18,7 +18,7 @@ /* Bare en linje under, som resten av toppfeltet */ .game-search__input { width: 100%; - padding: 0.4rem 0; + padding: 0.4rem 2rem 0.4rem 0; /* topp, høyre, bunn, venstre: plass til X-en til høyre */ font: inherit; color: var(--text-h); background: transparent; @@ -39,6 +39,32 @@ box-shadow: 0 1px 0 var(--text-h); } +/* X-knappen helt til høyre inne i søkefeltet, uten boks som resten av tekstknappene */ +.game-search__clear { + position: absolute; /* plasseres i forhold til .game-search, som har position: relative */ + top: 0; + right: 0; + height: 100%; + min-width: 32px; /* stort nok til å treffe med finger */ + padding: 0; + font: inherit; + font-size: 1.3em; + line-height: 1; + color: var(--text); + background: none; + border: 0; + cursor: pointer; +} + +.game-search__clear:hover { + color: var(--text-h); +} + +.game-search__clear:focus-visible { + outline: 2px solid var(--text-h); + outline-offset: 2px; +} + /* Forslagene legger seg over innholdet under, med tynn linje rundt i stedet for skygge */ .game-search__popup { position: absolute; From f9c9530b20c06ae4fab024d6e582c76d40b2dbd9 Mon Sep 17 00:00:00 2001 From: Clemens Beese Date: Tue, 20 Oct 2026 18:11:32 +0200 Subject: [PATCH 3/6] feat(frontend): logoen er lenke til forsiden --- frontend/src/components/Logo/Logo.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/Logo/Logo.tsx b/frontend/src/components/Logo/Logo.tsx index df41c8f..a7d6e64 100644 --- a/frontend/src/components/Logo/Logo.tsx +++ b/frontend/src/components/Logo/Logo.tsx @@ -1,13 +1,19 @@ +import { Link } from 'react-router'; import turbine from '../../assets/drawings/turbin.webp'; import './Logo.css'; -/** Damp-logoen: turbintegningen med navnet under. */ -export function Logo() { +interface LogoProps { + /** Nullstiller søk og filtre når man går til forsiden */ + onHome: () => void; +} + +/** Damp-logoen: turbintegningen med navnet under. Lenke til forsiden. */ +export function Logo({ onHome }: LogoProps) { return ( -
- {/* Tegningen er pynt (alt=""), navnet under er det skjermlesere leser */} + + {/* Tegningen er pynt (alt=""), lenken får navnet sitt fra aria-label */} Damp -
+ ); } From c44363e089ed080b10641a9f7452ab34bc48247b Mon Sep 17 00:00:00 2001 From: Clemens Beese Date: Tue, 20 Oct 2026 18:11:32 +0200 Subject: [PATCH 4/6] style(frontend): logo som lenke med synlig fokus --- frontend/src/components/Logo/Logo.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontend/src/components/Logo/Logo.css b/frontend/src/components/Logo/Logo.css index 030f080..3906dca 100644 --- a/frontend/src/components/Logo/Logo.css +++ b/frontend/src/components/Logo/Logo.css @@ -6,6 +6,17 @@ gap: 10px; } +/* Logoen er en lenke: ingen understrek eller lenkefarge, men synlig fokus for tastatur */ +.logo { + color: inherit; + text-decoration: none; +} + +.logo:focus-visible { + outline: 2px solid var(--text-h); + outline-offset: 4px; +} + .logo img { display: block; height: 44px; From 02a7db9152e3f9f322992240e7c1c5924f2f1a9c Mon Sep 17 00:00:00 2001 From: Clemens Beese Date: Tue, 20 Oct 2026 18:11:32 +0200 Subject: [PATCH 5/6] =?UTF-8?q?feat(frontend):=20send=20onHome=20og=20null?= =?UTF-8?q?stilling=20av=20s=C3=B8kefelt=20gjennom=20Header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Header/Header.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx index ad0f70b..c9dd7f3 100644 --- a/frontend/src/components/Header/Header.tsx +++ b/frontend/src/components/Header/Header.tsx @@ -10,6 +10,8 @@ interface HeaderProps { favoritesCount: number; showFavorites: boolean; onToggleFavorites: () => void; + onHome: () => void; + searchResetKey: number; } /** @@ -19,15 +21,17 @@ interface HeaderProps { export function Header({ onSearch, onSelectGame, + onHome, + searchResetKey, favoritesCount, showFavorites, onToggleFavorites, }: HeaderProps) { return (
- +
- +