Skip to content

Commit

Permalink
feat: Support dark mode better (casbin#141)
Browse files Browse the repository at this point in the history
  • Loading branch information
HashCookie authored Jul 22, 2024
1 parent 4e59fb9 commit feb8fac
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 10 deletions.
7 changes: 5 additions & 2 deletions app/components/LanguageMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import { useLang } from '@/app/context/LangContext';

const LanguageMenu = () => {
const { lang, setLang } = useLang();
const { lang, setLang, theme } = useLang();
const [mounted, setMounted] = useState(false);

const languageNames = {
Expand All @@ -32,6 +32,8 @@ const LanguageMenu = () => {
};

const currentLanguage = languageNames[lang] || 'Unknown';
const textClass = clsx(theme === 'dark' ? 'text-gray-200' : 'text-gray-800');
const iconFilterClass = clsx(theme === 'dark' ? 'filter invert' : '');

useEffect(() => {
setMounted(true);
Expand All @@ -56,12 +58,13 @@ const LanguageMenu = () => {
'text-[#453d7a]',
'bg-[#efefef]',
'hover:bg-[#453d7d] hover:text-white',
textClass,
)}
>
<img
src="LanguageSwitching.svg"
alt="Language"
className="w-6 h-6 mr-1"
className={clsx('w-6 h-6 mr-1', iconFilterClass)}
style={{
transition: 'filter 0.5s',
}}
Expand Down
17 changes: 10 additions & 7 deletions app/components/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const EditorScreen = () => {
const { message } = extractPageContent(boxType, t, lang);
return message;
};
const { t, lang } = useLang();
const { t, lang, theme } = useLang();

useEffect(() => {
const fetchCasbinVersion = async () => {
Expand Down Expand Up @@ -87,6 +87,7 @@ export const EditorScreen = () => {
});
}
}, [modelKind, modelText, policy, customConfig, request, enforceContextData, enforcer, setEcho, setRequestResult]);
const textClass = clsx(theme === 'dark' ? 'text-gray-200' : 'text-gray-800');

return (
<div className="flex flex-row h-full">
Expand Down Expand Up @@ -115,7 +116,7 @@ export const EditorScreen = () => {
</svg>
</button>

<div className={'pt-6 h-12 flex items-center font-bold'}>{open && <div>{t('Custom config')}</div>}</div>
<div className={'pt-6 h-12 flex items-center font-bold'}>{open && <div className={textClass}>{t('Custom config')}</div>}</div>
<div className="flex-grow overflow-auto h-full">
{open && (
<div className="flex flex-col h-full">
Expand All @@ -142,7 +143,7 @@ export const EditorScreen = () => {
<div className="flex flex-row gap-1 pt-4 flex-1 overflow-hidden">
<div className="flex-1 flex flex-col h-full overflow-hidden">
<div className={clsx('h-10 pl-2', 'flex items-center justify-start gap-2')}>
<div className={'font-bold'}>{t('Model')}</div>
<div className={clsx(textClass, 'font-bold')}>{t('Model')}</div>
<select
value={modelKind}
onChange={(e) => {
Expand Down Expand Up @@ -208,7 +209,7 @@ export const EditorScreen = () => {
</div>
<div className="flex-1 flex flex-col h-full overflow-hidden">
<div className="h-10 font-bold flex items-center justify-between">
<div>{t('Policy')}</div>
<div className={textClass}>{t('Policy')}</div>
<div className="text-right font-bold mr-4 text-sm text-[#e13c3c]">
<a href={`https://github.com/casbin/node-casbin/releases/tag/v${casbinVersion}`} target="_blank" rel="noopener noreferrer">
Node-Casbin v{casbinVersion}
Expand Down Expand Up @@ -244,7 +245,7 @@ export const EditorScreen = () => {
<div className="flex flex-row gap-1 pt-2 flex-1 overflow-hidden">
<div className="flex-1 flex flex-col h-full overflow-hidden">
<div className={clsx('h-10 pl-2', 'flex items-center justify-start gap-3')}>
<div className={'font-bold'}>{t('Request')}</div>
<div className={clsx(textClass, 'font-bold')}>{t('Request')}</div>
<div className={'space-x-2'}>
<input
className={clsx('w-7 pl-1', 'border border-black rounded')}
Expand Down Expand Up @@ -309,7 +310,7 @@ export const EditorScreen = () => {
</div>
<div className="flex-1 flex flex-col h-full overflow-hidden">
<div className={clsx('h-10 font-bold', 'flex items-center justify-between')}>
<div>{t('Enforcement Result')}</div>
<div className={textClass}>{t('Enforcement Result')}</div>
<div className="mr-4">
<SidePanelChat ref={sidePanelChatRef} />
</div>
Expand Down Expand Up @@ -459,7 +460,9 @@ export const EditorScreen = () => {
{t('COPY')}
</button>
)}
<div style={{ display: 'inline-block', marginRight: 'auto' }}>{echo}</div>
<div style={{ display: 'inline-block', marginRight: 'auto' }} className={textClass}>
{echo}
</div>
<div className="mr-3">
<LanguageMenu />
</div>
Expand Down
24 changes: 23 additions & 1 deletion app/context/LangContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,22 @@ type LangContextType = {
lang: string;
setLang: (lang: string) => void;
t: (key: string) => string;
theme: 'light' | 'dark';
toggleTheme: () => void;
};

const LangContext = createContext<LangContextType | undefined>(undefined);

export const LangProvider = ({ children }: { children: ReactNode }) => {
const [lang, setLangState] = useState('en');
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const urlTheme = urlParams.get('theme');
const savedLang = localStorage.getItem('lang');

if (savedLang) {
setLangState(savedLang);
} else {
Expand All @@ -43,6 +49,16 @@ export const LangProvider = ({ children }: { children: ReactNode }) => {
setLangState(defaultLang);
localStorage.setItem('lang', defaultLang);
}

if (urlTheme === 'dark' || urlTheme === 'light') {
setTheme(urlTheme);
localStorage.setItem('theme', urlTheme);
} else {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
setTheme(prefersDark ? 'dark' : 'light');
localStorage.setItem('theme', prefersDark ? 'dark' : 'light');
}

setIsLoading(false);
}, []);

Expand All @@ -51,6 +67,12 @@ export const LangProvider = ({ children }: { children: ReactNode }) => {
localStorage.setItem('lang', newLang);
};

const toggleTheme = () => {
const newTheme = theme === 'light' ? 'dark' : 'light';
setTheme(newTheme);
localStorage.setItem('theme', newTheme);
};

const t = (key: string) => {
const value = translations[lang][key];
return value || key;
Expand All @@ -60,7 +82,7 @@ export const LangProvider = ({ children }: { children: ReactNode }) => {
return null;
}

return <LangContext.Provider value={{ lang, setLang, t }}>{children}</LangContext.Provider>;
return <LangContext.Provider value={{ lang, setLang, t, theme, toggleTheme }}>{children}</LangContext.Provider>;
};

export const useLang = () => {
Expand Down

0 comments on commit feb8fac

Please sign in to comment.