From 99a9e954f706fc17434b172d249968b6b8723ac5 Mon Sep 17 00:00:00 2001
From: "ALMAZROUEI Shamma (2021) WKIS203"
 <shamma.almazrouei.2021@live.rhul.ac.uk>
Date: Wed, 9 Apr 2025 19:21:58 +0530
Subject: [PATCH] fix accessibility options

---
 uniconnect-app/app/app/layout.tsx             |   6 +-
 uniconnect-app/app/globals.css                |  90 ++++++-----
 uniconnect-app/app/layout.tsx                 |  12 +-
 uniconnect-app/app/page.tsx                   |   4 +-
 .../components/navigation/accessibility.tsx   |  57 ++++++-
 .../components/navigation/main-nav.tsx        |   2 +-
 .../contexts/accessibility-context.tsx        | 106 +++++++++++++
 uniconnect-app/tailwind.config.ts             | 150 +++++++++---------
 8 files changed, 293 insertions(+), 134 deletions(-)
 create mode 100644 uniconnect-app/contexts/accessibility-context.tsx

diff --git a/uniconnect-app/app/app/layout.tsx b/uniconnect-app/app/app/layout.tsx
index 1034bf1..e465c1c 100644
--- a/uniconnect-app/app/app/layout.tsx
+++ b/uniconnect-app/app/app/layout.tsx
@@ -32,11 +32,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
     <div className='grid min-h-screen w-full md:grid-cols-[220px_1fr] lg:grid-cols-[280px_1fr]'>
       <div className='hidden border-r bg-muted/40 md:block'>
         <div className='flex h-full max-h-screen flex-col gap-8 lg:gap-12'>
-          <div className='flex h-16 items-center px-4 lg:h-[72px] lg:px-6'>
-            <Link href='/app' className=''>
-              <Logo className='h-8 w-auto' />
-            </Link>
-          </div>
+          <div className='flex h-16 items-center px-4 lg:h-[32px] lg:px-6'></div>
 
           <div className='flex-1'>
             <nav className='grid items-start px-2 text-sm font-medium lg:px-4'>
diff --git a/uniconnect-app/app/globals.css b/uniconnect-app/app/globals.css
index edd81d5..23de7e2 100644
--- a/uniconnect-app/app/globals.css
+++ b/uniconnect-app/app/globals.css
@@ -5,57 +5,63 @@
 @layer base {
   :root {
     --background: 0 0% 100%;
-    --foreground: 222.2 84% 4.9%;
+    --foreground: 20 14.3% 4.1%;
     --card: 0 0% 100%;
-    --card-foreground: 222.2 84% 4.9%;
+    --card-foreground: 20 14.3% 4.1%;
     --popover: 0 0% 100%;
-    --popover-foreground: 222.2 84% 4.9%;
-    --primary: 221.2 83.2% 53.3%;
-    --primary-foreground: 210 40% 98%;
-    --secondary: 210 40% 96.1%;
-    --secondary-foreground: 222.2 47.4% 11.2%;
-    --muted: 210 40% 96.1%;
-    --muted-foreground: 215.4 16.3% 46.9%;
-    --accent: 210 40% 96.1%;
-    --accent-foreground: 222.2 47.4% 11.2%;
+    --popover-foreground: 20 14.3% 4.1%;
+    --primary: 47.9 95.8% 53.1%;
+    --primary-foreground: 26 83.3% 14.1%;
+    --secondary: 60 4.8% 95.9%;
+    --secondary-foreground: 24 9.8% 10%;
+    --muted: 60 4.8% 95.9%;
+    --muted-foreground: 25 5.3% 44.7%;
+    --accent: 60 4.8% 95.9%;
+    --accent-foreground: 24 9.8% 10%;
     --destructive: 0 84.2% 60.2%;
-    --destructive-foreground: 210 40% 98%;
-    --border: 214.3 31.8% 91.4%;
-    --input: 214.3 31.8% 91.4%;
-    --ring: 221.2 83.2% 53.3%;
+    --destructive-foreground: 60 9.1% 97.8%;
+    --border: 20 5.9% 90%;
+    --input: 20 5.9% 90%;
+    --ring: 20 14.3% 4.1%;
     --radius: 0.3rem;
     --chart-1: 12 76% 61%;
     --chart-2: 173 58% 39%;
     --chart-3: 197 37% 24%;
     --chart-4: 43 74% 66%;
     --chart-5: 27 87% 67%;
+
+    --text-size-multiplier: 1;
   }
 
-  .dark {
-    --background: 222.2 84% 4.9%;
-    --foreground: 210 40% 98%;
-    --card: 222.2 84% 4.9%;
-    --card-foreground: 210 40% 98%;
-    --popover: 222.2 84% 4.9%;
-    --popover-foreground: 210 40% 98%;
-    --primary: 217.2 91.2% 59.8%;
-    --primary-foreground: 222.2 47.4% 11.2%;
-    --secondary: 217.2 32.6% 17.5%;
-    --secondary-foreground: 210 40% 98%;
-    --muted: 217.2 32.6% 17.5%;
-    --muted-foreground: 215 20.2% 65.1%;
-    --accent: 217.2 32.6% 17.5%;
-    --accent-foreground: 210 40% 98%;
-    --destructive: 0 62.8% 30.6%;
-    --destructive-foreground: 210 40% 98%;
-    --border: 217.2 32.6% 17.5%;
-    --input: 217.2 32.6% 17.5%;
-    --ring: 224.3 76.3% 48%;
-    --chart-1: 220 70% 50%;
-    --chart-2: 160 60% 45%;
-    --chart-3: 30 80% 55%;
-    --chart-4: 280 65% 60%;
-    --chart-5: 340 75% 55%;
+  .high-contrast {
+    --background: 0 0% 0%;
+    --foreground: 0 0% 100%;
+    --card: 0 0% 0%;
+    --card-foreground: 0 0% 100%;
+    --popover: 0 0% 0%;
+    --popover-foreground: 0 0% 100%;
+    --primary: 0 0% 100%;
+    --primary-foreground: 0 0% 0%;
+    --secondary: 0 0% 20%;
+    --secondary-foreground: 0 0% 100%;
+    --muted: 0 0% 20%;
+    --muted-foreground: 0 0% 90%;
+    --accent: 0 0% 20%;
+    --accent-foreground: 0 0% 100%;
+    --destructive: 0 100% 50%;
+    --destructive-foreground: 0 0% 100%;
+    --border: 0 0% 40%;
+    --input: 0 0% 40%;
+    --ring: 0 0% 100%;
+
+    filter: invert(0.1) hue-rotate(240deg);
+    color: white !important;
+
+    --chart-1: 0 100% 70%;
+    --chart-2: 120 100% 70%;
+    --chart-3: 240 100% 70%;
+    --chart-4: 60 100% 70%;
+    --chart-5: 300 100% 70%;
   }
 }
 
@@ -66,4 +72,8 @@
   body {
     @apply bg-background text-foreground;
   }
+
+  html {
+    font-size: calc(100% * var(--text-size-multiplier));
+  }
 }
diff --git a/uniconnect-app/app/layout.tsx b/uniconnect-app/app/layout.tsx
index c96db98..4400cbb 100644
--- a/uniconnect-app/app/layout.tsx
+++ b/uniconnect-app/app/layout.tsx
@@ -6,6 +6,8 @@ import './globals.css';
 import Nav from '@/components/navigation/nav';
 import AccessibilityMenu from '@/components/accessibility/accessibilityMenu';
 
+import { AccessibilityProvider } from '@/contexts/accessibility-context';
+
 const geistSans = localFont({
   src: './fonts/GeistVF.woff',
   variable: '--font-geist-sans',
@@ -30,13 +32,15 @@ export default function RootLayout({
 }>) {
   return (
     <html
-      className={`${geistSans.variable} ${geistMono.variable} antialiased`}
+      className={`${geistSans.variable} ${geistMono.variable} antialiased high-contrast`}
       lang='en'
     >
       <body className='relative'>
-        <AccessibilityMenu />
-        <Nav />
-        {children}
+        <AccessibilityProvider>
+          <AccessibilityMenu />
+          <Nav />
+          {children}
+        </AccessibilityProvider>
       </body>
     </html>
   );
diff --git a/uniconnect-app/app/page.tsx b/uniconnect-app/app/page.tsx
index 3d6be58..7f348c1 100644
--- a/uniconnect-app/app/page.tsx
+++ b/uniconnect-app/app/page.tsx
@@ -37,7 +37,7 @@ export default function LandingPage() {
         {/* Feaures section */}
         <section className='w-full py-12 md:py-24 lg:py-32 bg-gray-100 dark:bg-gray-800'>
           <div className='container px-4 md:px-6 mx-auto'>
-            <h2 className='text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl text-center mb-8'>
+            <h2 className='text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl text-center mb-8 text-black'>
               Features
             </h2>
             <div className='grid gap-6 sm:grid-cols-2 lg:grid-cols-4'>
@@ -130,7 +130,7 @@ export default function LandingPage() {
           <div className='container px-4 md:px-6 mx-auto'>
             <div className='flex flex-col items-center space-y-4 text-center'>
               <div className='space-y-2'>
-                <h2 className='text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl'>
+                <h2 className='text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl text-black'>
                   Join Uniconnect Today
                 </h2>
                 <p className='mx-auto max-w-[700px] text-gray-500 md:text-xl dark:text-gray-400'>
diff --git a/uniconnect-app/components/navigation/accessibility.tsx b/uniconnect-app/components/navigation/accessibility.tsx
index dfa569f..4475b97 100644
--- a/uniconnect-app/components/navigation/accessibility.tsx
+++ b/uniconnect-app/components/navigation/accessibility.tsx
@@ -1,3 +1,5 @@
+'use client';
+
 import { AArrowDown, AArrowUp, ALargeSmall, Languages } from 'lucide-react';
 
 import Container from '@/components/ui/container';
@@ -12,15 +14,41 @@ import {
 import { Label } from '@/components/ui/label';
 import { Switch } from '@/components/ui/switch';
 import { Button } from '@/components/ui/button';
+import { useAccessibility } from '@/contexts/accessibility-context';
+import { useState, useEffect } from 'react';
 
 export default function Accessibility() {
+  const {
+    highContrast,
+    toggleHighContrast,
+    increaseTextSize,
+    decreaseTextSize,
+    resetTextSize,
+  } = useAccessibility();
+
+  const [language, setLanguage] = useState('english');
+
+  const [isHighContrast, setIsHighContrast] = useState(false);
+
+  useEffect(() => {
+    setIsHighContrast(highContrast);
+  }, [highContrast]);
+
+  const handleLanguageChange = (value: string) => {
+    setLanguage(value);
+  };
+
   return (
-    <div className='bg-blue-100 border-b border-zinc-30'>
-      <Container className='py-4  justify-between hidden md:flex'>
+    <div className='bg-yellow-100 border-b border-zinc-30'>
+      <Container className='py-4 justify-between hidden md:flex'>
         <div className='flex items-center gap-x-2'>
-          <Languages />
-          <Select defaultValue='english'>
-            <SelectTrigger className='w-[180px] font-medium border-muted-foreground'>
+          <Languages className='text-black' />
+          <Select
+            defaultValue='english'
+            value={language}
+            onValueChange={handleLanguageChange}
+          >
+            <SelectTrigger className='w-[180px] font-medium border-black text-black'>
               <SelectValue />
             </SelectTrigger>
             <SelectContent className='font-medium'>
@@ -36,8 +64,17 @@ export default function Accessibility() {
         </div>
 
         <div className='flex items-center space-x-2'>
-          <Switch id='high-contrast-mode' />
-          <Label htmlFor='high-contrast-mode' className='font-medium'>
+          <Switch
+            id='high-contrast-mode'
+            checked={isHighContrast}
+            onCheckedChange={() => {
+              toggleHighContrast();
+            }}
+          />
+          <Label
+            htmlFor='high-contrast-mode'
+            className='font-medium text-black'
+          >
             High Contrast
           </Label>
         </div>
@@ -47,6 +84,8 @@ export default function Accessibility() {
             variant='outline'
             size='icon'
             className='border-muted-foreground'
+            onClick={decreaseTextSize}
+            aria-label='Decrease text size'
           >
             <AArrowDown />
           </Button>
@@ -54,6 +93,8 @@ export default function Accessibility() {
             variant='outline'
             size='icon'
             className='border-muted-foreground'
+            onClick={resetTextSize}
+            aria-label='Reset text size'
           >
             <ALargeSmall />
           </Button>
@@ -61,6 +102,8 @@ export default function Accessibility() {
             variant='outline'
             size='icon'
             className='border-muted-foreground'
+            onClick={increaseTextSize}
+            aria-label='Increase text size'
           >
             <AArrowUp />
           </Button>
diff --git a/uniconnect-app/components/navigation/main-nav.tsx b/uniconnect-app/components/navigation/main-nav.tsx
index d19ed97..7102953 100644
--- a/uniconnect-app/components/navigation/main-nav.tsx
+++ b/uniconnect-app/components/navigation/main-nav.tsx
@@ -16,7 +16,7 @@ import {
 
 export default function MainNav() {
   return (
-    <div className='bg-blue-100 border-b border-zinc-500'>
+    <div className='bg-yellow-100 border-b border-zinc-500'>
       <Container className='py-4 flex justify-between items-center'>
         <Link href='/'>
           <h1 className='flex items-center gap-x-2'>
diff --git a/uniconnect-app/contexts/accessibility-context.tsx b/uniconnect-app/contexts/accessibility-context.tsx
new file mode 100644
index 0000000..d83f2f1
--- /dev/null
+++ b/uniconnect-app/contexts/accessibility-context.tsx
@@ -0,0 +1,106 @@
+'use client';
+
+import type React from 'react';
+import { createContext, useContext, useState, useEffect } from 'react';
+
+type AccessibilityContextType = {
+  highContrast: boolean;
+  toggleHighContrast: () => void;
+  textSize: number;
+  increaseTextSize: () => void;
+  decreaseTextSize: () => void;
+  resetTextSize: () => void;
+};
+
+const AccessibilityContext = createContext<
+  AccessibilityContextType | undefined
+>(undefined);
+
+export const AccessibilityProvider = ({
+  children,
+}: {
+  children: React.ReactNode;
+}) => {
+  const [highContrast, setHighContrast] = useState(false);
+  const [textSize, setTextSize] = useState(1);
+
+  useEffect(() => {
+    const savedHighContrast = localStorage.getItem('highContrast') === 'true';
+    const savedTextSize = Number.parseFloat(
+      localStorage.getItem('textSize') || '1'
+    );
+
+    setHighContrast(savedHighContrast);
+    setTextSize(savedTextSize);
+
+    applyHighContrast(savedHighContrast);
+    applyTextSize(savedTextSize);
+  }, []);
+
+  const applyHighContrast = (enabled: boolean) => {
+    if (enabled) {
+      document.documentElement.classList.add('high-contrast');
+    } else {
+      document.documentElement.classList.remove('high-contrast');
+    }
+  };
+
+  const applyTextSize = (size: number) => {
+    document.documentElement.style.setProperty(
+      '--text-size-multiplier',
+      size.toString()
+    );
+  };
+
+  const toggleHighContrast = () => {
+    const newValue = !highContrast;
+    setHighContrast(newValue);
+    localStorage.setItem('highContrast', newValue.toString());
+    applyHighContrast(newValue);
+  };
+
+  const increaseTextSize = () => {
+    const newSize = Math.min(textSize + 0.1, 1.5); // Max 1.5x
+    setTextSize(newSize);
+    localStorage.setItem('textSize', newSize.toString());
+    applyTextSize(newSize);
+  };
+
+  const decreaseTextSize = () => {
+    const newSize = Math.max(textSize - 0.1, 0.8); // Min 0.8x
+    setTextSize(newSize);
+    localStorage.setItem('textSize', newSize.toString());
+    applyTextSize(newSize);
+  };
+
+  const resetTextSize = () => {
+    setTextSize(1);
+    localStorage.setItem('textSize', '1');
+    applyTextSize(1);
+  };
+
+  return (
+    <AccessibilityContext.Provider
+      value={{
+        highContrast,
+        toggleHighContrast,
+        textSize,
+        increaseTextSize,
+        decreaseTextSize,
+        resetTextSize,
+      }}
+    >
+      {children}
+    </AccessibilityContext.Provider>
+  );
+};
+
+export const useAccessibility = () => {
+  const context = useContext(AccessibilityContext);
+  if (context === undefined) {
+    throw new Error(
+      'useAccessibility must be used within an AccessibilityProvider'
+    );
+  }
+  return context;
+};
diff --git a/uniconnect-app/tailwind.config.ts b/uniconnect-app/tailwind.config.ts
index da45954..f32dce7 100644
--- a/uniconnect-app/tailwind.config.ts
+++ b/uniconnect-app/tailwind.config.ts
@@ -8,81 +8,81 @@ const config: Config = {
     './app/**/*.{js,ts,jsx,tsx,mdx}',
   ],
   theme: {
-  	extend: {
-  		fontFamily: {
-  			sans: ['var(--font-geist-sans)'],
-  			mono: ['var(--font-geist-mono)']
-  		},
-  		colors: {
-  			background: 'hsl(var(--background))',
-  			foreground: 'hsl(var(--foreground))',
-  			card: {
-  				DEFAULT: 'hsl(var(--card))',
-  				foreground: 'hsl(var(--card-foreground))'
-  			},
-  			popover: {
-  				DEFAULT: 'hsl(var(--popover))',
-  				foreground: 'hsl(var(--popover-foreground))'
-  			},
-  			primary: {
-  				DEFAULT: 'hsl(var(--primary))',
-  				foreground: 'hsl(var(--primary-foreground))'
-  			},
-  			secondary: {
-  				DEFAULT: 'hsl(var(--secondary))',
-  				foreground: 'hsl(var(--secondary-foreground))'
-  			},
-  			muted: {
-  				DEFAULT: 'hsl(var(--muted))',
-  				foreground: 'hsl(var(--muted-foreground))'
-  			},
-  			accent: {
-  				DEFAULT: 'hsl(var(--accent))',
-  				foreground: 'hsl(var(--accent-foreground))'
-  			},
-  			destructive: {
-  				DEFAULT: 'hsl(var(--destructive))',
-  				foreground: 'hsl(var(--destructive-foreground))'
-  			},
-  			border: 'hsl(var(--border))',
-  			input: 'hsl(var(--input))',
-  			ring: 'hsl(var(--ring))',
-  			chart: {
-  				'1': 'hsl(var(--chart-1))',
-  				'2': 'hsl(var(--chart-2))',
-  				'3': 'hsl(var(--chart-3))',
-  				'4': 'hsl(var(--chart-4))',
-  				'5': 'hsl(var(--chart-5))'
-  			}
-  		},
-  		borderRadius: {
-  			lg: 'var(--radius)',
-  			md: 'calc(var(--radius) - 2px)',
-  			sm: 'calc(var(--radius) - 4px)'
-  		},
-  		keyframes: {
-  			'accordion-down': {
-  				from: {
-  					height: '0'
-  				},
-  				to: {
-  					height: 'var(--radix-accordion-content-height)'
-  				}
-  			},
-  			'accordion-up': {
-  				from: {
-  					height: 'var(--radix-accordion-content-height)'
-  				},
-  				to: {
-  					height: '0'
-  				}
-  			}
-  		},
-  		animation: {
-  			'accordion-down': 'accordion-down 0.2s ease-out',
-  			'accordion-up': 'accordion-up 0.2s ease-out'
-  		}
-  	}
+    extend: {
+      fontFamily: {
+        sans: ['var(--font-geist-sans)'],
+        mono: ['var(--font-geist-mono)'],
+      },
+      colors: {
+        background: 'hsl(var(--background))',
+        foreground: 'hsl(var(--foreground))',
+        card: {
+          DEFAULT: 'hsl(var(--card))',
+          foreground: 'hsl(var(--card-foreground))',
+        },
+        popover: {
+          DEFAULT: 'hsl(var(--popover))',
+          foreground: 'hsl(var(--popover-foreground))',
+        },
+        primary: {
+          DEFAULT: 'hsl(var(--primary))',
+          foreground: 'hsl(var(--primary-foreground))',
+        },
+        secondary: {
+          DEFAULT: 'hsl(var(--secondary))',
+          foreground: 'hsl(var(--secondary-foreground))',
+        },
+        muted: {
+          DEFAULT: 'hsl(var(--muted))',
+          foreground: 'hsl(var(--muted-foreground))',
+        },
+        accent: {
+          DEFAULT: 'hsl(var(--accent))',
+          foreground: 'hsl(var(--accent-foreground))',
+        },
+        destructive: {
+          DEFAULT: 'hsl(var(--destructive))',
+          foreground: 'hsl(var(--destructive-foreground))',
+        },
+        border: 'hsl(var(--border))',
+        input: 'hsl(var(--input))',
+        ring: 'hsl(var(--ring))',
+        chart: {
+          '1': 'hsl(var(--chart-1))',
+          '2': 'hsl(var(--chart-2))',
+          '3': 'hsl(var(--chart-3))',
+          '4': 'hsl(var(--chart-4))',
+          '5': 'hsl(var(--chart-5))',
+        },
+      },
+      borderRadius: {
+        lg: 'var(--radius)',
+        md: 'calc(var(--radius) - 2px)',
+        sm: 'calc(var(--radius) - 4px)',
+      },
+      keyframes: {
+        'accordion-down': {
+          from: {
+            height: '0',
+          },
+          to: {
+            height: 'var(--radix-accordion-content-height)',
+          },
+        },
+        'accordion-up': {
+          from: {
+            height: 'var(--radix-accordion-content-height)',
+          },
+          to: {
+            height: '0',
+          },
+        },
+      },
+      animation: {
+        'accordion-down': 'accordion-down 0.2s ease-out',
+        'accordion-up': 'accordion-up 0.2s ease-out',
+      },
+    },
   },
   plugins: [require('tailwindcss-animate')],
 };
-- 
GitLab