Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/components/SearchField.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* Skiller søkefeltet fra lenkene under.
padding-bottom er luft over streken, margin-bottom er luft under den. */
.search-field {
padding-bottom: 24px;
margin-bottom: 24px;
border-bottom: 1px solid var(--border);
}

.search-field input {
width: 100%;
font-size: 18px;
padding: 8px 12px;
box-sizing: border-box; /* padding regnes inn i bredden, så feltet ikke blir bredere enn sidebaren */
border-radius: 10px; /* samme runding som filmkortene */
border: 1px solid var(--border);
}

/* Skjuler elementet visuelt uten å fjerne det fra DOM-en,
slik at skjermlesere fortsatt leser opp teksten (labelen over). */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
32 changes: 32 additions & 0 deletions src/components/SearchField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import './SearchField.css';

// value og onChange heter det samme som på et vanlig <input>, med vilje:
// da leser <SearchField value={query} onChange={setQuery} /> som HTML folk kan fra før.
type SearchFieldProps = {
value: string;
onChange: (value: string) => void;
};

// Komponenten har ingen egen state. Teksten kommer inn som prop og sendes ut igjen
// via onChange - den som bruker komponenten (App) eier verdien. Det kalles et
// "kontrollert" felt, og er grunnen til at søket kan tømmes utenfra når man
// klikker på en lenke i sidebaren.
export function SearchField({ value, onChange }: SearchFieldProps) {
return (
<div className="search-field">
{/* htmlFor må matche input-ens id. Det er koblingen som gjør at skjermlesere
vet hva feltet er til for, og at man kan klikke på labelen for å fokusere feltet. */}
<label htmlFor="movie-search" className="visually-hidden">
Søk etter filmer eller skuespillere
</label>
<input
id="movie-search"
type="search"
placeholder="Søk..."
value={value}
// e.target.value er teksten som står i feltet akkurat nå
onChange={(e) => onChange(e.target.value)}
/>
</div>
);
}
37 changes: 10 additions & 27 deletions src/components/sidebar.css
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@


/* Skjuler elementet visuelt uten å fjerne det fra DOM-en,
slik at skjermlesere fortsatt leser opp teksten (f.eks. labelen over). */
.visually-hidden {
position: absolute; /* tar det ut av normal layout-flyt */
width: 1px;
height: 1px; /* krymper det til nesten ingenting */
padding: 0;
margin: -1px; /* trikser bort avrundingsproblemer i noen nettlesere */
overflow: hidden; /* skjuler alt innhold som stikker utenfor 1x1px */
clip: rect(0, 0, 0, 0); /* eldre metode for å "klippe bort" innholdet visuelt */
white-space: nowrap; /* hindrer teksten fra å brekke og bli synlig */
border: 0;
}

/* Gjør at #-lenker (som href="#populaere") scroller mykt i stedet for å hoppe brått. */
html {
scroll-behavior: smooth;
Expand All @@ -22,17 +6,16 @@ html {
.sidebar {
text-align: left;
flex: 1 1 0; /* 2 del av 4 = 1/4 av siden */
}

.sidebar-search {
margin-bottom: 28px; /* luft mellom søkefelt og lenkene */
}

.sidebar-search input {
width: 100%;
font-size: 18px;
padding: 8px 12px;
box-sizing: border-box;
position: sticky; /*betyr at elementet oppfører seg helt normalt helt til man scroller forbi "top" grensen som man også setter */
top: 24px;
/*
Tips fra claude her:
når dere gjør siden responsiv er overflow-x: hidden på body eller #root
et vanlig triks mot horisontal scroll, og det dreper sticky umiddelbart uten noen feilmelding.
Hvis sidebaren blir høyere enn skjermen (flere lenker, eller favoritter listet i sidebaren senere),
legg til max-height: 100vh; og overflow-y: auto; i samme regel. Da får sidebaren sin egen scroll i
stedet for at bunnen blir utilgjengelig.
*/
}

.sidebar-nav {
Expand Down
19 changes: 4 additions & 15 deletions src/components/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import './sidebar.css';

import { SearchField } from './SearchField';

type SidebarProps = {
onSearch?: (query: string) => void;
Expand All @@ -18,18 +18,8 @@ export function Sidebar({onSearch, searchValue}: SidebarProps) {

<aside className="sidebar">

<div className="sidebar-search">
<label htmlFor="movie-search" className="visually-hidden">
Søk etter filmer eller skuespillere!
</label>
<input
id="movie-search"
type="search"
placeholder="Søk..."
value={searchValue ?? ''}
onChange={(e) => onSearch?.(e.target.value)}
/>
</div>
<SearchField value={searchValue ?? ''} onChange={(v) => onSearch?.(v)} />

<nav aria-label="Innhold på siden">
<ul className="sidebar-nav">
{sections.map((section) =>(
Expand All @@ -52,5 +42,4 @@ export function Sidebar({onSearch, searchValue}: SidebarProps) {
</nav>
</aside>
);
}

}