From 50f6c8a033afd30d09d157e9721611ca75b0532b Mon Sep 17 00:00:00 2001 From: Vegard Date: Wed, 15 Apr 2026 10:01:06 +0200 Subject: [PATCH 01/10] feat: save theme preference to local storage and apply theme on load --- package-lock.json | 39 ------------- src/app/_components/UI/ThemeEnabler.tsx | 15 +++++ src/app/layout.tsx | 2 + .../(user-admin)/theme/ThemeForm.tsx | 56 +------------------ .../[username]/(user-admin)/theme/theme.ts | 54 ++++++++++++++++++ 5 files changed, 73 insertions(+), 93 deletions(-) create mode 100644 src/app/_components/UI/ThemeEnabler.tsx create mode 100644 src/app/users/[username]/(user-admin)/theme/theme.ts diff --git a/package-lock.json b/package-lock.json index 37264cd94..4042a0664 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3053,9 +3053,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3076,9 +3073,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3099,9 +3093,6 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3122,9 +3113,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3145,9 +3133,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5138,9 +5123,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5155,9 +5137,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5172,9 +5151,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5189,9 +5165,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5206,9 +5179,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5223,9 +5193,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5240,9 +5207,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5257,9 +5221,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ diff --git a/src/app/_components/UI/ThemeEnabler.tsx b/src/app/_components/UI/ThemeEnabler.tsx new file mode 100644 index 000000000..95e983bc2 --- /dev/null +++ b/src/app/_components/UI/ThemeEnabler.tsx @@ -0,0 +1,15 @@ +'use client' + +import { applyTheme, themes } from '@/app/users/[username]/(user-admin)/theme/theme' +import { useEffect } from 'react' +import type { ThemeName } from '@/app/users/[username]/(user-admin)/theme/theme' + +export default function ThemeEnabler() { + useEffect(() => { + const saved = localStorage.getItem('theme') as ThemeName + if (saved && themes[saved]) { + applyTheme(saved) + } + }, []) + return () +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 2fb96f7a1..22b41c340 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -19,6 +19,7 @@ import { unwrapActionReturn } from './redirectToErrorPage' import { frontpageAuth } from '@/services/frontpage/auth' import { ServerSession } from '@/auth/session/ServerSession' import type { Metadata } from 'next' +import ThemeEnabler from '@/UI/ThemeEnabler' config.autoAddCss = false @@ -51,6 +52,7 @@ export default async function RootLayout({ children }: PropTypes) { return ( + diff --git a/src/app/users/[username]/(user-admin)/theme/ThemeForm.tsx b/src/app/users/[username]/(user-admin)/theme/ThemeForm.tsx index 5f11011d5..60b4980eb 100644 --- a/src/app/users/[username]/(user-admin)/theme/ThemeForm.tsx +++ b/src/app/users/[username]/(user-admin)/theme/ThemeForm.tsx @@ -1,62 +1,10 @@ 'use client' import styles from './page.module.scss' - -enum ThemeName { - Standard = 'Standard', - Light = 'Light', - Solarized = 'Solarized', - StjerneInnbygger = 'StjerneInnbygger', -} - -type ThemeColors = { - primary: string; - secondary: string; - layer: string; - text: string; - textMuted: string; -}; - -const themes: Record = { - [ThemeName.Standard]: { - primary: 'hsl(210, 70%, 50%)', - secondary: 'hsl(210, 5%, 12%)', - layer: 'hsl(210, 0%, 0%, 20%)', - text: 'hsl(0, 0%, 80%)', - textMuted: 'hsl(0, 0%, 70%)', - }, - [ThemeName.Light]: { - primary: 'hsl(210, 98%, 50%)', - secondary: 'hsl(210, 18%, 95%)', - layer: 'hsl(0, 0%, 0%, 5%)', - text: 'hsl(0, 0%, 10%)', - textMuted: 'hsl(0, 0%, 20%)', - }, - [ThemeName.Solarized]: { - primary: 'hsl(210, 98%, 50%)', - secondary: 'hsl(44, 87%, 94%)', - layer: 'hsl(0, 0%, 50%, 15%)', - text: 'hsl(196, 13%, 45%)', - textMuted: 'hsl(180, 7%, 60%)', - }, - [ThemeName.StjerneInnbygger]: { - primary: 'hsl(207, 91%, 65%)', - secondary: 'hsl(202, 64%, 10%)', - layer: 'hsla(211, 48.1%, 35.5%, 0.18)', - text: 'hsl(0, 0%, 80%)', - textMuted: 'hsl(0, 0%, 70%)', - }, -} +import { themes, applyTheme } from './theme' +import type { ThemeName } from './theme' export default function ThemeForm() { - function applyTheme(name: ThemeName): void { - const colors = themes[name] - const root = document.documentElement - Object.entries(colors).forEach(([key, value]) => { - root.style.setProperty(`--${key}`, value) - }) - } - return (
{Object.entries(themes).map(([name, colors]) => ( diff --git a/src/app/users/[username]/(user-admin)/theme/theme.ts b/src/app/users/[username]/(user-admin)/theme/theme.ts new file mode 100644 index 000000000..8fad25ee2 --- /dev/null +++ b/src/app/users/[username]/(user-admin)/theme/theme.ts @@ -0,0 +1,54 @@ +export enum ThemeName { + Standard = 'Standard', + Light = 'Light', + Solarized = 'Solarized', + StjerneInnbygger = 'StjerneInnbygger', +} + +type ThemeColors = { + primary: string; + secondary: string; + layer: string; + text: string; + textMuted: string; +}; + +export const themes: Record = { + [ThemeName.Standard]: { + primary: 'hsl(210, 70%, 50%)', + secondary: 'hsl(210, 5%, 12%)', + layer: 'hsl(210, 0%, 0%, 20%)', + text: 'hsl(0, 0%, 80%)', + textMuted: 'hsl(0, 0%, 70%)', + }, + [ThemeName.Light]: { + primary: 'hsl(210, 98%, 50%)', + secondary: 'hsl(210, 18%, 95%)', + layer: 'hsl(0, 0%, 0%, 5%)', + text: 'hsl(0, 0%, 10%)', + textMuted: 'hsl(0, 0%, 20%)', + }, + [ThemeName.Solarized]: { + primary: 'hsl(210, 98%, 50%)', + secondary: 'hsl(44, 87%, 94%)', + layer: 'hsl(0, 0%, 50%, 15%)', + text: 'hsl(196, 13%, 45%)', + textMuted: 'hsl(180, 7%, 60%)', + }, + [ThemeName.StjerneInnbygger]: { + primary: 'hsl(207, 91%, 65%)', + secondary: 'hsl(202, 64%, 10%)', + layer: 'hsla(211, 48.1%, 35.5%, 0.18)', + text: 'hsl(0, 0%, 80%)', + textMuted: 'hsl(0, 0%, 70%)', + }, +} + +export function applyTheme(name: ThemeName): void { + localStorage.setItem('theme', name) + const colors = themes[name] + const root = document.documentElement + Object.entries(colors).forEach(([key, value]) => { + root.style.setProperty(`--${key}`, value) + }) +} From f612602c8824d49dd71e3e3c32aefee3891b4a0c Mon Sep 17 00:00:00 2001 From: Vegard Date: Wed, 15 Apr 2026 10:45:30 +0200 Subject: [PATCH 02/10] feat: update navbar items to include theme --- src/app/users/[username]/(user-admin)/layout.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/app/users/[username]/(user-admin)/layout.tsx b/src/app/users/[username]/(user-admin)/layout.tsx index 0df1eadf9..10a6f48a2 100644 --- a/src/app/users/[username]/(user-admin)/layout.tsx +++ b/src/app/users/[username]/(user-admin)/layout.tsx @@ -6,7 +6,15 @@ import PageWrapper from '@/components/PageWrapper/PageWrapper' import { SubPageNavBar, SubPageNavBarItem } from '@/components/NavBar/SubPageNavBar/SubPageNavBar' import { flairAuth } from '@/services/flairs/auth' import { notFound } from 'next/navigation' -import { faCircleDot, faCog, faHatWizard, faKey, faPaperPlane, faUser } from '@fortawesome/free-solid-svg-icons' +import { + faCircleDot, + faCog, + faHatWizard, + faKey, + faPaperPlane, + faSwatchbook, + faUser +} from '@fortawesome/free-solid-svg-icons' import type { ReactNode } from 'react' import type { PropTypes } from '@/app/users/[username]/page' import type { Metadata } from 'next' @@ -53,6 +61,9 @@ export default async function UserAdmin({ children, params }: PropTypes & { chil {canAssignFlairs.authorized && Kapper } + + Tema + Innstillinger From 34023eb2182f1a2e29b467508de5d794a566ea3c Mon Sep 17 00:00:00 2001 From: Vegard Date: Wed, 15 Apr 2026 20:37:50 +0200 Subject: [PATCH 03/10] feat: svg versions of logos --- .../standard_store/images/logo_simple.svg | 21 +++++++++++++++++++ .../standard_store/images/logo_white.svg | 21 +++++++++++++++++++ .../images/omega_logo_white.svg | 21 +++++++++++++++++++ .../seeder/standard_store/images/pwa.svg | 21 +++++++++++++++++++ .../standard_store/images/vevcom_logo.svg | 21 +++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 src/prisma/seeder/standard_store/images/logo_simple.svg create mode 100644 src/prisma/seeder/standard_store/images/logo_white.svg create mode 100644 src/prisma/seeder/standard_store/images/omega_logo_white.svg create mode 100644 src/prisma/seeder/standard_store/images/pwa.svg create mode 100644 src/prisma/seeder/standard_store/images/vevcom_logo.svg diff --git a/src/prisma/seeder/standard_store/images/logo_simple.svg b/src/prisma/seeder/standard_store/images/logo_simple.svg new file mode 100644 index 000000000..517b46d3c --- /dev/null +++ b/src/prisma/seeder/standard_store/images/logo_simple.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/prisma/seeder/standard_store/images/logo_white.svg b/src/prisma/seeder/standard_store/images/logo_white.svg new file mode 100644 index 000000000..51b0b91f1 --- /dev/null +++ b/src/prisma/seeder/standard_store/images/logo_white.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/prisma/seeder/standard_store/images/omega_logo_white.svg b/src/prisma/seeder/standard_store/images/omega_logo_white.svg new file mode 100644 index 000000000..a9bd78793 --- /dev/null +++ b/src/prisma/seeder/standard_store/images/omega_logo_white.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/prisma/seeder/standard_store/images/pwa.svg b/src/prisma/seeder/standard_store/images/pwa.svg new file mode 100644 index 000000000..2f345f291 --- /dev/null +++ b/src/prisma/seeder/standard_store/images/pwa.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/prisma/seeder/standard_store/images/vevcom_logo.svg b/src/prisma/seeder/standard_store/images/vevcom_logo.svg new file mode 100644 index 000000000..12d1ead42 --- /dev/null +++ b/src/prisma/seeder/standard_store/images/vevcom_logo.svg @@ -0,0 +1,21 @@ + + + + + + + + + From a704774ed6c10733c9402fc48fb6eae2ff9075b8 Mon Sep 17 00:00:00 2001 From: Vegard Date: Thu, 16 Apr 2026 10:49:58 +0200 Subject: [PATCH 04/10] feat: main landmark --- src/app/layout.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 22b41c340..411df7736 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -61,9 +61,9 @@ export default async function RootLayout({ children }: PropTypes) {
-
+
{children} -
+
From ea12ed3a047d9abd033ab0936a12573347fb661b Mon Sep 17 00:00:00 2001 From: Vegard Date: Thu, 16 Apr 2026 14:17:26 +0200 Subject: [PATCH 05/10] feat: more svgs --- .../standard_store/images/magisk_hatt.svg | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/prisma/seeder/standard_store/images/magisk_hatt.svg diff --git a/src/prisma/seeder/standard_store/images/magisk_hatt.svg b/src/prisma/seeder/standard_store/images/magisk_hatt.svg new file mode 100644 index 000000000..1d0cef255 --- /dev/null +++ b/src/prisma/seeder/standard_store/images/magisk_hatt.svg @@ -0,0 +1,21 @@ + + + + + + + + + From 1130d3ece5e5108ecd830fd8bca7d57a8c4ea9ad Mon Sep 17 00:00:00 2001 From: Vegard Date: Thu, 16 Apr 2026 14:18:20 +0200 Subject: [PATCH 06/10] refactor: update background color for menu items to improve light mode --- src/app/_components/NavBar/Menu.module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/_components/NavBar/Menu.module.scss b/src/app/_components/NavBar/Menu.module.scss index 33b7e9cdd..79249aeac 100644 --- a/src/app/_components/NavBar/Menu.module.scss +++ b/src/app/_components/NavBar/Menu.module.scss @@ -37,7 +37,7 @@ width: 30 * ohma.$gap; text-decoration: none; padding: 2 * ohma.$gap; - @include ohma.layer(); + background: ohma.$colors-secondary; border-radius: ohma.$rounding; color: ohma.$colors-text; display: flex; From f90b7c472eeb932fdb53f33c68f32ab842a2b77a Mon Sep 17 00:00:00 2001 From: Vegard Date: Tue, 21 Apr 2026 10:56:47 +0200 Subject: [PATCH 07/10] accessibility: add descriptive aria-labels to Link components across admin and user pages --- src/app/_components/NavBar/NavBar.tsx | 2 +- src/app/admin/BackButton.tsx | 2 +- src/app/admin/dots/DotList.tsx | 13 ++++++++----- src/app/admin/groups/[id]/page.tsx | 16 ++++++++++++++-- src/app/admin/lockers/page.tsx | 4 ++-- src/app/admin/product/page.tsx | 7 ++++++- src/app/admin/schools/SchoolAdminList.tsx | 4 +++- src/app/news/page.tsx | 2 +- 8 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/app/_components/NavBar/NavBar.tsx b/src/app/_components/NavBar/NavBar.tsx index 4b5c3f1b4..565cbc1eb 100644 --- a/src/app/_components/NavBar/NavBar.tsx +++ b/src/app/_components/NavBar/NavBar.tsx @@ -41,7 +41,7 @@ export default async function NavBar({ profile, canEditSpecialCmsImage }: PropTy readSpecialCmsImageAction={readSpecialCmsImageFrontpage} updateCmsImageAction={updateSpecialCmsImageFrontpage} > - + { diff --git a/src/app/admin/BackButton.tsx b/src/app/admin/BackButton.tsx index 167a195df..28bceab5d 100644 --- a/src/app/admin/BackButton.tsx +++ b/src/app/admin/BackButton.tsx @@ -17,7 +17,7 @@ export default function BackButton({ className }: PropTypes) { const href = `/${pathname?.split('/').slice(1, -1).join('/')}` return ( - + ) diff --git a/src/app/admin/dots/DotList.tsx b/src/app/admin/dots/DotList.tsx index d29675f79..447687a85 100644 --- a/src/app/admin/dots/DotList.tsx +++ b/src/app/admin/dots/DotList.tsx @@ -51,11 +51,14 @@ export default function DotList({ onlyActive }: PropTypes) { }> - + {onlyActive ? 'Vis alle prikker' : 'Vis aktive prikker'} diff --git a/src/app/admin/groups/[id]/page.tsx b/src/app/admin/groups/[id]/page.tsx index 73a2aec21..983651829 100644 --- a/src/app/admin/groups/[id]/page.tsx +++ b/src/app/admin/groups/[id]/page.tsx @@ -71,11 +71,23 @@ export default async function GroupAdmin({ params }: PropTypes) { ) : ( ( group.groupType === 'CLASS' && - Gå til Kalsseadministrasjon + + Gå til Klasseadministrasjon + ) || ( group.groupType === 'OMEGA_MEMBERSHIP_GROUP' && - Gå til opptakssiden + + Gå til opptakssiden + ) ) } diff --git a/src/app/admin/lockers/page.tsx b/src/app/admin/lockers/page.tsx index dc45ce416..5b682432a 100644 --- a/src/app/admin/lockers/page.tsx +++ b/src/app/admin/lockers/page.tsx @@ -5,8 +5,8 @@ export default function Locker() { return (

Skapreservasjoner

- Oppret ny skaplokasjon - Opprett nytt skap + Oppret ny skaplokasjon + Opprett nytt skap
) } diff --git a/src/app/admin/product/page.tsx b/src/app/admin/product/page.tsx index 9967fc91b..b72af908b 100644 --- a/src/app/admin/product/page.tsx +++ b/src/app/admin/product/page.tsx @@ -33,7 +33,12 @@ export default async function ProductPage() { {sortObjectsByName(products).map(product => - + {product.name} diff --git a/src/app/admin/schools/SchoolAdminList.tsx b/src/app/admin/schools/SchoolAdminList.tsx index 108ac927b..433b6f7b6 100644 --- a/src/app/admin/schools/SchoolAdminList.tsx +++ b/src/app/admin/schools/SchoolAdminList.tsx @@ -18,7 +18,9 @@ export async function SchoolAdminList({ schools }: PropTypes) { {schools.map(school => ( - + {school.id} {school.name} diff --git a/src/app/news/page.tsx b/src/app/news/page.tsx index 080fa4e59..59efab93c 100644 --- a/src/app/news/page.tsx +++ b/src/app/news/page.tsx @@ -13,7 +13,7 @@ export default async function NewsArtilces() { - Arkivet + Arkivet { canCreateNews && ( From 5e27670e4147ff29cf1c5915e0a612535668dab9 Mon Sep 17 00:00:00 2001 From: Vegard Bauge <47744141+kake21@users.noreply.github.com> Date: Tue, 21 Apr 2026 12:06:29 +0200 Subject: [PATCH 08/10] Update src/app/_components/UI/ThemeEnabler.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/app/_components/UI/ThemeEnabler.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/_components/UI/ThemeEnabler.tsx b/src/app/_components/UI/ThemeEnabler.tsx index 95e983bc2..9be60e523 100644 --- a/src/app/_components/UI/ThemeEnabler.tsx +++ b/src/app/_components/UI/ThemeEnabler.tsx @@ -11,5 +11,5 @@ export default function ThemeEnabler() { applyTheme(saved) } }, []) - return () + return null } From d2af6a263c433704fce50db9945e514d7d219b0e Mon Sep 17 00:00:00 2001 From: Vegard Bauge <47744141+kake21@users.noreply.github.com> Date: Tue, 21 Apr 2026 12:07:06 +0200 Subject: [PATCH 09/10] Update src/app/admin/lockers/page.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/app/admin/lockers/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/admin/lockers/page.tsx b/src/app/admin/lockers/page.tsx index 5b682432a..03022a4ae 100644 --- a/src/app/admin/lockers/page.tsx +++ b/src/app/admin/lockers/page.tsx @@ -5,7 +5,7 @@ export default function Locker() { return (

Skapreservasjoner

- Oppret ny skaplokasjon + Opprett ny skaplokasjon Opprett nytt skap
) From beb8805e098316c4a2342e43b693f34c52d8c3d7 Mon Sep 17 00:00:00 2001 From: Vegard Bauge <47744141+kake21@users.noreply.github.com> Date: Tue, 21 Apr 2026 12:07:25 +0200 Subject: [PATCH 10/10] Update src/app/users/[username]/(user-admin)/theme/theme.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/app/users/[username]/(user-admin)/theme/theme.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/users/[username]/(user-admin)/theme/theme.ts b/src/app/users/[username]/(user-admin)/theme/theme.ts index 8fad25ee2..ed9c0336b 100644 --- a/src/app/users/[username]/(user-admin)/theme/theme.ts +++ b/src/app/users/[username]/(user-admin)/theme/theme.ts @@ -17,21 +17,21 @@ export const themes: Record = { [ThemeName.Standard]: { primary: 'hsl(210, 70%, 50%)', secondary: 'hsl(210, 5%, 12%)', - layer: 'hsl(210, 0%, 0%, 20%)', + layer: 'hsla(210, 0%, 0%, 0.2)', text: 'hsl(0, 0%, 80%)', textMuted: 'hsl(0, 0%, 70%)', }, [ThemeName.Light]: { primary: 'hsl(210, 98%, 50%)', secondary: 'hsl(210, 18%, 95%)', - layer: 'hsl(0, 0%, 0%, 5%)', + layer: 'hsla(0, 0%, 0%, 0.05)', text: 'hsl(0, 0%, 10%)', textMuted: 'hsl(0, 0%, 20%)', }, [ThemeName.Solarized]: { primary: 'hsl(210, 98%, 50%)', secondary: 'hsl(44, 87%, 94%)', - layer: 'hsl(0, 0%, 50%, 15%)', + layer: 'hsla(0, 0%, 50%, 0.15)', text: 'hsl(196, 13%, 45%)', textMuted: 'hsl(180, 7%, 60%)', },