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
149 changes: 108 additions & 41 deletions client/src/App.css
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
/* ---------- Header ---------- */

.site-header {
--header-end: #1b6a8c;

position: relative;
padding: 1rem 1rem 2.75rem;
background: linear-gradient(var(--navy-900), #0d2d54);
z-index: 5;
padding: 1.25rem 1rem 1.8rem;
background: linear-gradient(var(--navy-900), #0f3d68 45%, var(--header-end));
color: var(--eggshell);
}

.site-header :focus-visible {
outline-color: var(--blue-100);
}

/* Bølgekant mot eggeskall-bakgrunnen. Fargen må være skrevet inn i SVG-en. */
/*
* Bølgekanten henger under toppen i samme farge som bunnen av den, så den
* passer mot alt som ligger under, både eggeskallbakgrunnen og kartet.
*/
.site-header::after {
content: '';
position: absolute;
top: 100%;
right: 0;
bottom: -1px;
left: 0;
height: 1.25rem;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 20'%3E%3Cpath fill='%23f6f2e7' d='M0 20v-8q12-8 24 0t24 0 24 0 24 0v8Z'/%3E%3C/svg%3E")
repeat-x bottom / 6rem 1.25rem;
height: 0.5rem;
background: var(--header-end);
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 8'%3E%3Cpath d='M0 4q12-8 24 0t24 0 24 0 24 0V0H0Z'/%3E%3C/svg%3E")
repeat-x top / 6rem 0.5rem;
}

/* Sidemargen holder tittelen unna hjørneknappene. */
Expand All @@ -29,27 +36,58 @@
text-align: center;
}

/* Tittelen har fast høyde og én linje, så toppen er like høy på alle sider. */
.site-title h1 {
display: flex;
align-items: center;
justify-content: center;
gap: 0.6rem;
height: 1.4em;
margin: 0;
font-size: clamp(2rem, 5vw, 3rem);
line-height: 1.1;
font-size: clamp(2rem, 5vw, 2.85rem);
line-height: 1.4;
}

.site-title h1 > :first-child {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.site-title h1 > :last-child:not(:first-child) {
display: flex;
flex: none;
}

.site-title .avatar {
width: 1em;
height: 1em;
border-width: 2px;
}

/* På smale skjermer kan undertittelen gå over to linjer, og plassen er alltid satt av. */
@media (max-width: 40rem) {
.site-title p {
min-height: 3em;
}
}

/* Tagline med tynne streker på hver side. */
.site-title p {
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
margin: 0.25rem 0 0;
gap: 0.6rem;
margin: 0.4rem 0 0;
color: var(--blue-100);
font-size: clamp(1rem, 2.5vw, 1.25rem);
font-size: clamp(0.95rem, 2.5vw, 1.2rem);
}

.site-title p::before,
.site-title p::after {
content: '';
width: clamp(1rem, 6vw, 3rem);
width: clamp(0.75rem, 5vw, 2.5rem);
height: 1px;
background: var(--blue-300);
opacity: 0.7;
Expand Down Expand Up @@ -199,24 +237,6 @@
box-shadow: none;
}

.home-link {
position: absolute;
top: 0.5rem;
left: 3.75rem;
z-index: 3;
grid-auto-flow: column;
gap: 0.5rem;
height: 2.75rem;
padding-inline: 1rem;
border-radius: 999px;
text-decoration: none;
}

.home-link svg {
width: 1.25rem;
height: 1.25rem;
}

.map-control:disabled {
opacity: 0.4;
cursor: default;
Expand All @@ -236,10 +256,10 @@

.main-nav ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
gap: 0.5rem;
max-width: 52rem;
margin: 1rem auto 0;
grid-template-columns: repeat(auto-fit, minmax(6.25rem, 1fr));
gap: 0.4rem;
max-width: 44rem;
margin: 0.85rem auto 0;
padding: 0;
list-style: none;
}
Expand All @@ -248,11 +268,12 @@
display: flex;
align-items: center;
justify-content: center;
gap: 0.45rem;
padding: 0.6rem 0.75rem;
border-radius: 0.6rem;
background: var(--navy-700);
gap: 0.4rem;
padding: 0.3rem 0.55rem;
border-radius: 0.5rem;
background: rgb(10 34 64 / 0.6);
color: var(--eggshell);
font-size: 0.85rem;
font-weight: 600;
text-decoration: none;
transition:
Expand All @@ -263,8 +284,8 @@

.nav-icon {
flex: none;
width: 1.2rem;
height: 1.2rem;
width: 1rem;
height: 1rem;
}

.main-nav a:hover {
Expand Down Expand Up @@ -643,3 +664,49 @@
.status-closed {
color: var(--closed);
}

/* Innholdet tones inn når man bytter side, så overgangen blir myk. */
@keyframes page-in {
from {
opacity: 0;
}
}

main {
animation: page-in 0.2s ease-out;
}

/* ---------- Bunn ---------- */

/* Rotfeltet fyller vinduet, så sitatet havner nederst også på korte sider. */
#root {
display: flex;
flex-direction: column;
min-height: 100dvh;
}

.site-footer {
margin-top: auto;
padding: 3.5rem 1.5rem 2.5rem;
color: #8f765a;
font-family: Georgia, 'Times New Roman', serif;
font-size: 0.85rem;
font-style: italic;
text-align: center;
}

.site-footer figure,
.site-footer blockquote,
.site-footer p {
margin: 0;
}

.site-footer figure {
max-width: 32rem;
margin-inline: auto;
}

.site-footer figcaption {
margin-top: 0.3rem;
font-size: 0.8rem;
}
19 changes: 17 additions & 2 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { useEffect } from 'react'
import './App.css'
import { PageFooter } from './components/PageFooter'
import { PageHeader } from './components/PageHeader'
import { useRoute } from './hooks/useRoute'
import { ChallengesPage } from './pages/ChallengesPage'
import { HomePage } from './pages/HomePage'
Expand All @@ -13,9 +16,21 @@ const pages = {
}

function App() {
const Page = pages[useRoute()]
const route = useRoute()
const Page = pages[route]

return <Page />
// Hver side starter øverst, ikke der forrige side var rullet til.
useEffect(() => {
window.scrollTo(0, 0)
}, [route])

return (
<>
<PageHeader />
<Page key={route} />
<PageFooter />
</>
)
}

export default App
23 changes: 0 additions & 23 deletions client/src/components/HomeLink.tsx

This file was deleted.

20 changes: 15 additions & 5 deletions client/src/components/MainNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
HOME_HREF,
MAP_HREF,
USER_HREF,
useRoute,
} from '../hooks/useRoute'
import type { Route } from '../hooks/useRoute'

/** Felles tegning for ikonene: små, enkle strek-ikoner. */
function Icon({ children }: { children: ReactNode }) {
Expand All @@ -25,16 +27,17 @@ function Icon({ children }: { children: ReactNode }) {
)
}

/** Foreløpige lenker. «Hjem» er siden vi står på. */
/** Lenkene i hovednavigasjonen. «Ruter» har ingen side ennå. */
const links: {
label: string
icon: ReactNode
href?: string
current?: boolean
route?: Route
}[] = [
{
label: 'Utforsk',
href: MAP_HREF,
route: 'map',
// Kompass
icon: (
<Icon>
Expand All @@ -57,7 +60,7 @@ const links: {
{
label: 'Hjem',
href: HOME_HREF,
current: true,
route: 'home',
// Anker
icon: (
<Icon>
Expand All @@ -69,6 +72,7 @@ const links: {
{
label: 'Utfordringer',
href: CHALLENGES_HREF,
route: 'challenges',
// Flagg
icon: (
<Icon>
Expand All @@ -79,6 +83,7 @@ const links: {
{
label: 'Bruker',
href: USER_HREF,
route: 'user',
// Person
icon: (
<Icon>
Expand All @@ -90,12 +95,17 @@ const links: {
]

export function MainNav() {
const current = useRoute()

return (
<nav className="main-nav" aria-label="Hovednavigasjon">
<ul>
{links.map(({ label, icon, href, current }) => (
{links.map(({ label, icon, href, route }) => (
<li key={label}>
<a href={href ?? '#'} aria-current={current ? 'page' : undefined}>
<a
href={href ?? '#'}
aria-current={route === current ? 'page' : undefined}
>
{icon}
{label}
</a>
Expand Down
37 changes: 37 additions & 0 deletions client/src/components/PageFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useRoute } from '../hooks/useRoute'
import type { Route } from '../hooks/useRoute'

const quotes: Record<Route, { text: string; author: string }> = {
home: {
text: 'The sea, once it casts its spell, holds one in its net of wonder forever.',
author: 'Jacques-Yves Cousteau',
},
map: {
text: 'Man cannot discover new oceans unless he has the courage to lose sight of the shore.',
author: 'André Gide',
},
user: {
text: 'A sailor is an artist whose medium is the wind.',
author: 'Webb Chiles',
},
challenges: {
text: 'A smooth sea never made a skilled sailor.',
author: 'Franklin D. Roosevelt',
},
}

/** Et lite seilersitat nederst på hver side. */
export function PageFooter() {
const { text, author } = quotes[useRoute()]

return (
<footer className="site-footer">
<figure>
<blockquote>
<p>“{text}”</p>
</blockquote>
<figcaption>– {author}</figcaption>
</figure>
</footer>
)
}
Loading