Skip to content
Snippets Groups Projects
Commit 99a9e954 authored by ALMAZROUEI Shamma (2021) WKIS203's avatar ALMAZROUEI Shamma (2021) WKIS203
Browse files

fix accessibility options

parent 885208a7
Branches
No related tags found
No related merge requests found
......@@ -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'>
......
......@@ -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));
}
}
......@@ -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'>
<AccessibilityProvider>
<AccessibilityMenu />
<Nav />
{children}
</AccessibilityProvider>
</body>
</html>
);
......
......@@ -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'>
......
'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'>
<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>
......
......@@ -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'>
......
'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;
};
......@@ -11,38 +11,38 @@ const config: Config = {
extend: {
fontFamily: {
sans: ['var(--font-geist-sans)'],
mono: ['var(--font-geist-mono)']
mono: ['var(--font-geist-mono)'],
},
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))'
foreground: 'hsl(var(--card-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
foreground: 'hsl(var(--popover-foreground))',
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))'
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))'
foreground: 'hsl(var(--secondary-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
foreground: 'hsl(var(--accent-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
foreground: 'hsl(var(--destructive-foreground))',
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
......@@ -52,37 +52,37 @@ const config: Config = {
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
'5': 'hsl(var(--chart-5))',
},
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
sm: 'calc(var(--radius) - 4px)',
},
keyframes: {
'accordion-down': {
from: {
height: '0'
height: '0',
},
to: {
height: 'var(--radix-accordion-content-height)'
}
height: 'var(--radix-accordion-content-height)',
},
},
'accordion-up': {
from: {
height: 'var(--radix-accordion-content-height)'
height: 'var(--radix-accordion-content-height)',
},
to: {
height: '0'
}
}
height: '0',
},
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out'
}
}
'accordion-up': 'accordion-up 0.2s ease-out',
},
},
},
plugins: [require('tailwindcss-animate')],
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment