= ({ isLoggedIn, setIsLoggedIn }) => {
+ const [isDark, setIsDark] = useState(false);
+
+ // Dynamically include 'Gymnasts' only when logged in
+ const visibleLinks = [
+ { label: 'Search', path: '/' },
+ { label: 'Calculator', path: '/calculator' },
+ ...(isLoggedIn ? [{ label: 'Gymnasts', path: '/gymnasts' }] : []),
+ { label: 'About', path: '/about' },
+ ];
+
+ useEffect(() => {
+ document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
+ }, [isDark]);
+
+ const toggleTheme = () => {
+ setIsDark((prev) => !prev);
+ };
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/skipLink/SkipLink.module.css b/src/components/skipLink/SkipLink.module.css
new file mode 100644
index 0000000..c5876aa
--- /dev/null
+++ b/src/components/skipLink/SkipLink.module.css
@@ -0,0 +1,22 @@
+.skipLink {
+ position: absolute;
+ top: -999px;
+ left: -999px;
+ background: var(--accent-color, #C0D2F6);
+ color: var(--text-color-dark, #101844);
+ padding: var(--space-sm) var(--space-md);
+ border-radius: 0 0 var(--corner-radius, 8px) 0;
+ font-family: var(--font-family-text);
+ font-weight: 600;
+ text-decoration: none;
+ z-index: 9999;
+ transition: top 0.2s ease-in-out;
+ }
+
+ /* Vises helt øverst på skjermen når brukeren trykker Tab */
+ .skipLink:focus {
+ top: 0;
+ left: 0;
+ outline: 3px solid var(--text-color-dark, #101844);
+ outline-offset: 2px;
+ }
\ No newline at end of file
diff --git a/src/components/skipLink/SkipLink.tsx b/src/components/skipLink/SkipLink.tsx
new file mode 100644
index 0000000..58362c2
--- /dev/null
+++ b/src/components/skipLink/SkipLink.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import styles from './SkipLink.module.css';
+
+interface SkipLinkProps {
+ mainId?: string;
+}
+
+export const SkipLink: React.FC = ({ mainId = 'main-content' }) => {
+ return (
+
+ Skip to main content
+
+ );
+};
\ No newline at end of file
diff --git a/src/styles/variables.css b/src/styles/variables.css
index f6cac9a..bf18211 100644
--- a/src/styles/variables.css
+++ b/src/styles/variables.css
@@ -5,11 +5,12 @@
--accent-color: #C0D2F6;
--background-color: #ecf0f1;
--background-color-element: #F8F7F3;
+ --border-color: #EAE0CF;
/* Text colors */
--text-color: #101844;
--text-color-dark: #090F2F;
- --text-color-light: #EAE0CF;
+ --text-color-light: var(--border-color);
/* Font settings */
--font-family-title: 'Faustina', serif;
@@ -43,6 +44,7 @@
/* Dark mode colors */
[data-theme='dark'] {
/* Main Layout Colors */
+ --primary-color: #0A1A3C; /* Deep blue for primary elements */
--background-color: #090F2F; /* Dark blue background */
--header-background: #101844; /* Slightly lighter blue for nav */
--element-background: #18225C; /* Inputs, dropdowns, table background */
diff --git a/src/tests/setupTests.ts b/src/tests/setupTests.ts
new file mode 100644
index 0000000..fc45fe6
--- /dev/null
+++ b/src/tests/setupTests.ts
@@ -0,0 +1,8 @@
+///
+import '@testing-library/jest-dom';
+import { cleanup } from '@testing-library/react';
+import { afterEach } from 'vitest';
+
+afterEach(() => {
+ cleanup();
+});
\ No newline at end of file
diff --git a/tsconfig.app.json b/tsconfig.app.json
index 4ca43f0..f6157b7 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "incremental": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "es2023",
"lib": ["ES2023", "DOM"],
@@ -22,7 +23,7 @@
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
- /* Path alias used by shadcn/ui: @/ means src/. No baseUrl, TypeScript 6 deprecates it. */
+ /* Path alias used by shadcn/ui: @/ means erasableSyntaxOnlysrc/. No baseUrl, TypeScript 6 deprecates it. */
"paths": { "@/*": ["./src/*"] }
},
"include": ["src"]
diff --git a/tsconfig.json b/tsconfig.json
index 9e335f7..313ae6a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -9,8 +9,12 @@
}
],
"compilerOptions": {
+
"paths": {
"@/*": ["./src/*"]
- }
+ },
+ "types": ["jest", "@testing-library/jest-dom"]
+
+
}
}
diff --git a/vite.config.ts b/vite.config.ts
index 8e8ebb6..3c9c6f4 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,19 +1,18 @@
-import tailwindcss from '@tailwindcss/vite'
-import react, { reactCompilerPreset } from '@vitejs/plugin-react'
-import babel from '@rolldown/plugin-babel'
-import { fileURLToPath } from 'node:url'
-import { defineConfig } from 'vite'
+import tailwindcss from '@tailwindcss/vite';
+import react from '@vitejs/plugin-react';
+import { fileURLToPath } from 'node:url';
+import { defineConfig } from 'vitest/config';
-// https://vite.dev/config/
export default defineConfig({
base: '/project2/',
- plugins: [
- react(),
- babel({ presets: [reactCompilerPreset()] }),
- tailwindcss(),
- ],
+ plugins: [react(), tailwindcss()],
resolve: {
- // "@/components/ui/button" means "src/components/ui/button".
alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) },
},
-})
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ setupFiles: ['./src/tests/setupTests.ts'],
+ include: ['src/**/*.{test,spec}.{ts,tsx}'],
+ },
+});
\ No newline at end of file