-
- {/* Bytter mellom visning 1 (liste) og visning 2 (rutenett) */}
-
-
-
-
-
-
+ setShowFavorites((v) => !v)}
/>
-
+
+
+
+
{showFavorites ? 'Favoritter' : 'Søkeresultater'}
+
+ {/* Bytter mellom visning 1 (liste) og visning 2 (rutenett) */}
+
+
+
+
+
+
+
+
+ >
);
}
diff --git a/frontend/src/assets/drawings/tegning.webp b/frontend/src/assets/drawings/tegning.webp
new file mode 100644
index 0000000..1ac44aa
Binary files /dev/null and b/frontend/src/assets/drawings/tegning.webp differ
diff --git a/frontend/src/components/Header/Header.css b/frontend/src/components/Header/Header.css
new file mode 100644
index 0000000..b686e9e
--- /dev/null
+++ b/frontend/src/components/Header/Header.css
@@ -0,0 +1,33 @@
+.header {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+ padding: 16px 24px;
+ border-bottom: 1px solid var(--border);
+}
+
+.header__search {
+ flex: 1;
+}
+
+/* Menyen til høyre, i monospace som på clemenbe.no */
+.header__nav {
+ display: flex;
+ gap: 20px;
+ margin-left: auto;
+ font-family: var(--mono);
+ font-size: 15px;
+ white-space: nowrap;
+}
+
+/* Mobil: logo og meny på første linje, søket på hele andre linje */
+@media (max-width: 600px) {
+ .header {
+ flex-wrap: wrap;
+ gap: 12px 20px;
+ }
+ .header__search {
+ order: 3;
+ flex-basis: 100%;
+ }
+}
diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx
new file mode 100644
index 0000000..d62656b
--- /dev/null
+++ b/frontend/src/components/Header/Header.tsx
@@ -0,0 +1,44 @@
+import { Logo } from '../Logo/Logo';
+import { SearchBar } from '../SearchBar/SearchBar';
+import { ThemeToggle } from '../ThemeToggle/ThemeToggle';
+import './Header.css';
+
+interface HeaderProps {
+ search: string;
+ onSearchChange: (value: string) => void;
+ favoritesCount: number;
+ showFavorites: boolean;
+ onToggleFavorites: () => void;
+}
+
+/**
+ * Toppfeltet: logo, søk og meny (favoritter og tema), med søket øverst som på RAWG.
+ * Ingen bokser, bare tekst og en tynn linje under.
+ */
+export function Header({
+ search,
+ onSearchChange,
+ favoritesCount,
+ showFavorites,
+ onToggleFavorites,
+}: HeaderProps) {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/Logo/Logo.css b/frontend/src/components/Logo/Logo.css
index a91c291..008f112 100644
--- a/frontend/src/components/Logo/Logo.css
+++ b/frontend/src/components/Logo/Logo.css
@@ -1,37 +1,38 @@
-/* Smale skjermer: øverst til venstre, scroller vekk så den ikke dekker innholdet */
+/* Smale skjermer: første element i toppfeltet (Header) */
.logo {
- position: absolute;
- top: 20px;
- left: 20px;
- z-index: 10;
+ flex-shrink: 0;
}
.logo img {
display: block;
- height: 88px;
+ height: 44px;
width: auto;
}
-@media (max-width: 600px) {
- .logo img {
- height: 56px; /* Mindre logo på mobil */
- }
+/* Viser riktig logo for valgt tema. display: none skjuler den andre også for skjermlesere */
+.logo .logo__img--dark {
+ display: none;
+}
+:root[data-theme='dark'] .logo .logo__img--light {
+ display: none;
+}
+:root[data-theme='dark'] .logo .logo__img--dark {
+ display: block;
}
/* Brede skjermer: fast og midt i sidepanelet til venstre. Må stå sist i filen */
@media (min-width: 1320px) {
.logo {
position: fixed;
+ z-index: 10;
top: 20px;
- /* Midten av sidepanelet. 1126px er bredden på #root i index.css; endres den, må den endres her også */
+ /* Midten av sidepanelet. 1126px er bredden på #root i index.css */
left: calc((100vw - 1126px) / 4);
- /* Flytter logoen halvparten av sin egen bredde til venstre, så midten av logoen havner midt i panelet */
transform: translateX(-50%);
}
.logo img {
height: auto;
- /* Større: opptil 160px bred, men aldri bredere enn panelet minus 24px luft på hver side */
width: min(90px, calc((100vw - 1126px) / 2 - 48px));
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/components/Logo/Logo.tsx b/frontend/src/components/Logo/Logo.tsx
index 24eb3dc..baa3d28 100644
--- a/frontend/src/components/Logo/Logo.tsx
+++ b/frontend/src/components/Logo/Logo.tsx
@@ -2,12 +2,12 @@ import logoOnDark from '../../assets/logo/damp-logo-stacked-on-dark.svg';
import logoOnLight from '../../assets/logo/damp-logo-stacked-on-light.svg';
import './Logo.css';
-/** Damp-logoen (symbol med navnet under). Bytter versjon etter lyst/mørkt tema. */
+/** Damp-logoen (symbol med navnet under). CSS viser riktig versjon for valgt tema. */
export function Logo() {
return (
-
-
-
-
+
+
+
+
);
}
diff --git a/frontend/src/components/SearchBar/SearchBar.css b/frontend/src/components/SearchBar/SearchBar.css
index 949cd4b..231755b 100644
--- a/frontend/src/components/SearchBar/SearchBar.css
+++ b/frontend/src/components/SearchBar/SearchBar.css
@@ -11,12 +11,27 @@
border: 0;
}
+/* Bare en linje under, som et skjemafelt på papir */
.search-bar__input {
width: 100%;
- padding: 0.6rem 0.8rem;
+ padding: 0.4rem 0;
font: inherit;
- border: 1px solid #767676;
- border-radius: 0;
+ color: var(--text-h);
+ background: transparent;
+ border: 0;
+ border-bottom: 1px solid var(--text);
+ border-radius: 0;
-webkit-appearance: textfield;
appearance: textfield;
}
+
+.search-bar__input::placeholder {
+ color: var(--text);
+}
+
+/* Fokus: linjen blir mørkere og dobbelt så tykk, uten at noe flytter seg */
+.search-bar__input:focus-visible {
+ outline: none;
+ border-bottom-color: var(--text-h);
+ box-shadow: 0 1px 0 var(--text-h);
+}
diff --git a/frontend/src/components/ThemeToggle/ThemeToggle.tsx b/frontend/src/components/ThemeToggle/ThemeToggle.tsx
new file mode 100644
index 0000000..b26ba3a
--- /dev/null
+++ b/frontend/src/components/ThemeToggle/ThemeToggle.tsx
@@ -0,0 +1,32 @@
+import { useEffect, useState } from 'react';
+
+type Theme = 'light' | 'dark';
+
+/**
+ * Knapp som bytter mellom lyst og mørkt tema. Første gang brukes temaet scriptet
+ * i index.html har satt (systemets innstilling), deretter huskes valget i localStorage.
+ */
+export function ThemeToggle() {
+ const [theme, setTheme] = useState(() =>
+ document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light',
+ );
+
+ // Oppdaterer (som CSS-en leser) og husker valget
+ useEffect(() => {
+ document.documentElement.dataset.theme = theme;
+ try {
+ localStorage.setItem('theme', theme);
+ } catch {
+ // localStorage kan være blokkert (f.eks. privat modus), temaet virker likevel
+ }
+ }, [theme]);
+
+ const next = theme === 'dark' ? 'light' : 'dark';
+
+ return (
+ // Teksten sier hva knappen gjør, så skjermlesere og seende får samme informasjon
+
+ );
+}
diff --git a/frontend/src/index.css b/frontend/src/index.css
index f12902e..26d5f07 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,14 +1,15 @@
:root {
- --text: #6b6375;
- --text-h: #08060d;
- --bg: #fff;
- --border: #e5e4e7;
- --code-bg: #f4f3ec;
- --accent: #aa3bff;
- --accent-bg: rgba(170, 59, 255, 0.1);
- --accent-border: rgba(170, 59, 255, 0.5);
- --social-bg: rgba(244, 243, 236, 0.5);
- --shadow: rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
+ /* Lyst tema: varmt papirhvitt */
+ --text: #5c554c;
+ --text-h: #1f1b16;
+ --bg: #f8f5ee;
+ --border: #e3ddd1;
+ --code-bg: #efeae0;
+ --accent: #2c6370; /* fra Damp-logoen */
+ --accent-bg: rgba(44, 99, 112, 0.1);
+ --accent-border: rgba(44, 99, 112, 0.5);
+ --social-bg: rgba(239, 234, 224, 0.5);
+ --shadow: rgba(31, 27, 22, 0.1) 0 10px 15px -3px, rgba(31, 27, 22, 0.05) 0 4px 6px -2px;
--sans: system-ui, 'Segoe UI', Roboto, sans-serif;
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
@@ -16,7 +17,7 @@
font: 18px/145% var(--sans);
letter-spacing: 0.18px;
- color-scheme: light dark;
+ color-scheme: light;
color: var(--text);
background: var(--bg);
font-synthesis: none;
@@ -29,23 +30,20 @@
}
}
-@media (prefers-color-scheme: dark) {
- :root {
- --text: #9ca3af;
- --text-h: #f3f4f6;
- --bg: #16171d;
- --border: #2e303a;
- --code-bg: #1f2028;
- --accent: #c084fc;
- --accent-bg: rgba(192, 132, 252, 0.15);
- --accent-border: rgba(192, 132, 252, 0.5);
- --social-bg: rgba(47, 48, 58, 0.5);
- --shadow: rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
- }
-
- #social .button-icon {
- filter: invert(1) brightness(2);
- }
+/* Mørkt tema. data-theme settes på av scriptet i index.html og av ThemeToggle */
+:root[data-theme='dark'] {
+ color-scheme: dark;
+ /* Nøytral mørk med et lite grønt stikk */
+ --text: #a9aeab;
+ --text-h: #e8ebe9;
+ --bg: #191b1a;
+ --border: #2f3331;
+ --code-bg: #232625;
+ --accent: #6fa3ae; /* fra Damp-logoen (mørk versjon) */
+ --accent-bg: rgba(111, 163, 174, 0.15);
+ --accent-border: rgba(111, 163, 174, 0.5);
+ --social-bg: rgba(35, 38, 37, 0.5);
+ --shadow: rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
}
#root {
@@ -107,3 +105,67 @@ code {
padding: 4px 8px;
background: var(--code-bg);
}
+
+/*
+ * Tegningen i sidefeltet til venstre, under logoen
+ * Bare på brede skjermer der det er plass ved siden av innholdet. Som CSS-bakgrunn
+ * i en media query lastes bildet bare ned når det faktisk vises (bærekraft).
+ * 1126px er bredden på #root, samme tall som i Logo.css.
+ */
+@media (min-width: 1320px) {
+ body::before {
+ content: '';
+ position: fixed;
+ z-index: -1;
+ top: 50%;
+ left: calc((100vw - 1126px) / 4);
+ width: min(280px, calc((100vw - 1126px) / 2 - 48px));
+ aspect-ratio: 800 / 698;
+ transform: translate(-50%, -30%);
+ background: url('./assets/drawings/tegning.webp') center / contain no-repeat;
+ /* Det hvite papiret i skanningen smelter inn i papirbakgrunnen */
+ mix-blend-mode: multiply;
+ opacity: 0.85;
+ pointer-events: none;
+ }
+}
+
+/* Mørkt tema: inverterer tegningen så blyanten blir lys og papiret blir borte */
+@media (min-width: 1320px) {
+ :root[data-theme='dark'] body::before {
+ filter: invert(1);
+ mix-blend-mode: screen;
+ opacity: 0.6;
+ }
+}
+
+/* Tekstknapp uten boks (meny, tema, visning). Aktiv = mørkere tekst + strek under */
+.text-button {
+ padding: 0;
+ font: inherit;
+ color: var(--text);
+ background: none;
+ border: 0;
+ cursor: pointer;
+ text-underline-offset: 4px;
+}
+.text-button:hover,
+.text-button[aria-pressed='true'] {
+ color: var(--text-h);
+ text-decoration: underline;
+}
+.text-button:focus-visible {
+ outline: 2px solid var(--text-h);
+ outline-offset: 4px;
+}
+
+/* Seksjonsoverskrift i trykk-stil: små, sperrede versaler (som WRITING på clemenbe.no) */
+.label {
+ margin: 0;
+ font-family: var(--mono);
+ font-size: 13px;
+ font-weight: 500;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ color: var(--text-h);
+}