Files
imphnen-frontend-service/apps/hackathon/src/components/theme-toggle.tsx
T
bc5b072ad8 feat(hackathon): Improve dark mode and UI/UX in Hackathon website (#64)
* feat: update landing page

* feat: Add favicon and SEO (JSON-LD schema, meta tags)

- Add favicon image
- Add JSON-LD schema for Hackathon event
- Add react-helmet-async for managing meta tags

* chore: remove react-helmet-async

* chore: update landing page

* chore: update UI for signup and login

- add back button for better UX

* feat: add image loading state and skeleton UI for team dashboard

* fix: landing navbar not sticky to top, fix onboarding UI

* feat(hackathon): update UI

- Update dashboard, onboarding user, edit profile, and team layout
  to make it more consistent

* fix: optimize placeholder banner image & minor fix dark mode

* feat(hackathon): update landing page dark mode color scheme

* feat(hackathon): update auth page dark mode color scheme

* feat(hackathon): dashboard UI improvement and dark mode adjustment

* feat(hackathon): browse team page

- update dark mode color scheme
- add some border style to give outline and depth
- change emoji to icon

* feat(hackathon): update team page

- update dark mode color scheme for team page: view, team edit,
  and submit project page
- fix bug in chat where messages are displayed double
- make the form field size consistent

* feat(hackathon): update dark mode onboarding and edit profile

---------

Co-authored-by: Maulana Sodiqin <sodiqincahyana1@gmail.com>
Co-authored-by: Muhammad Zakir Ramadhan <61570975+zakirkun@users.noreply.github.com>
2025-11-27 15:12:45 +07:00

94 lines
2.2 KiB
TypeScript

import { FC } from 'react';
import { useTheme } from './theme-provider';
interface ThemeToggleProps {
className?: string;
}
// Sun icon for light mode
const SunIcon = () => (
<svg
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
);
// Moon icon for dark mode
const MoonIcon = () => (
<svg
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
/>
</svg>
);
// System icon (monitor)
const SystemIcon = () => (
<svg
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
/>
</svg>
);
export const ThemeToggle: FC<ThemeToggleProps> = ({ className = '' }) => {
const { theme, setTheme, resolvedTheme } = useTheme();
const cycleTheme = () => {
if (theme === 'light') setTheme('dark');
else if (theme === 'dark') setTheme('system');
else setTheme('light');
};
const getThemeLabel = () => {
if (theme === 'system') return 'System';
return theme === 'dark' ? 'Dark' : 'Light';
};
const renderIcon = () => {
if (theme === 'system') {
return <SystemIcon />;
}
return resolvedTheme === 'dark' ? <MoonIcon /> : <SunIcon />;
};
return (
<button
type="button"
onClick={cycleTheme}
className={`p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-neutral-800 transition-colors cursor-pointer text-gray-600 dark:text-neutral-200 ${className}`}
title={`Theme: ${getThemeLabel()}`}
aria-label={`Current theme: ${getThemeLabel()}. Click to change.`}
>
{renderIcon()}
</button>
);
};
export default ThemeToggle;