Replace theme dropdown with light/dark toggle
Made-with: Cursor
This commit is contained in:
parent
7a5eee8d21
commit
581f56c275
@ -1,47 +1,32 @@
|
||||
import { RiDice4Line } from 'react-icons/ri';
|
||||
import { SanitizedThemeConfig } from '../../interfaces/sanitized-config';
|
||||
import { LOCAL_STORAGE_KEY_NAME } from '../../constants';
|
||||
import { skeleton } from '../../utils';
|
||||
import { MouseEvent } from 'react';
|
||||
|
||||
/**
|
||||
* Renders a theme changer component.
|
||||
*
|
||||
* @param {Object} props - The props object.
|
||||
* @param {string} props.theme - The current theme.
|
||||
* @param {function} props.setTheme - A function to set the theme.
|
||||
* @param {boolean} props.loading - Whether the component is in a loading state.
|
||||
* @param {SanitizedThemeConfig} props.themeConfig - The theme configuration object.
|
||||
* @return {JSX.Element} The rendered theme changer component.
|
||||
* Renders a light/dark theme toggle.
|
||||
*/
|
||||
const ThemeChanger = ({
|
||||
theme,
|
||||
setTheme,
|
||||
loading,
|
||||
themeConfig,
|
||||
}: {
|
||||
theme: string;
|
||||
setTheme: (theme: string) => void;
|
||||
loading: boolean;
|
||||
themeConfig: SanitizedThemeConfig;
|
||||
}) => {
|
||||
const changeTheme = (
|
||||
e: MouseEvent<HTMLAnchorElement>,
|
||||
selectedTheme: string,
|
||||
) => {
|
||||
e.preventDefault();
|
||||
|
||||
document.querySelector('html')?.setAttribute('data-theme', selectedTheme);
|
||||
const isDark = theme === 'dark';
|
||||
|
||||
const applyTheme = (next: 'light' | 'dark') => {
|
||||
document.querySelector('html')?.setAttribute('data-theme', next);
|
||||
typeof window !== 'undefined' &&
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY_NAME, selectedTheme);
|
||||
|
||||
setTheme(selectedTheme);
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY_NAME, next);
|
||||
setTheme(next);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card overflow-visible shadow-lg card-sm bg-base-100">
|
||||
<div className="flex-row items-center space-x-4 flex pl-6 pr-2 py-4">
|
||||
<div className="flex-row items-center space-x-4 flex pl-6 pr-6 py-4">
|
||||
<div className="flex-1">
|
||||
<h5 className="card-title">
|
||||
{loading ? (
|
||||
@ -54,65 +39,30 @@ const ThemeChanger = ({
|
||||
<span className="text-base-content opacity-70">Theme</span>
|
||||
)}
|
||||
</h5>
|
||||
<span className="text-base-content/50 capitalize text-sm">
|
||||
<span className="text-base-content/50 text-sm">
|
||||
{loading
|
||||
? skeleton({ widthCls: 'w-16', heightCls: 'h-5' })
|
||||
: theme === 'light'
|
||||
? 'Light'
|
||||
: theme === 'dark'
|
||||
: isDark
|
||||
? 'Dark'
|
||||
: theme === themeConfig.defaultTheme
|
||||
? 'Default'
|
||||
: theme}
|
||||
: 'Light'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-0">
|
||||
{loading ? (
|
||||
skeleton({
|
||||
widthCls: 'w-12',
|
||||
heightCls: 'h-10',
|
||||
className: 'mr-6',
|
||||
heightCls: 'h-8',
|
||||
})
|
||||
) : (
|
||||
<div title="Change Theme" className="dropdown dropdown-end">
|
||||
<div
|
||||
tabIndex={0}
|
||||
className="btn btn-ghost m-1 normal-case opacity-50 text-base-content flex items-center whitespace-nowrap"
|
||||
>
|
||||
<RiDice4Line className="inline-block w-5 h-5 stroke-current" />
|
||||
</div>
|
||||
<div
|
||||
tabIndex={0}
|
||||
className="mt-16 overflow-y-auto shadow-2xl top-px dropdown-content max-h-96 min-w-max rounded-lg bg-base-200 text-base-content z-10"
|
||||
>
|
||||
<ul className="p-4 menu menu-sm">
|
||||
{[
|
||||
themeConfig.defaultTheme,
|
||||
...themeConfig.themes.filter(
|
||||
(item) => item !== themeConfig.defaultTheme,
|
||||
),
|
||||
].map((item, index) => (
|
||||
<li key={index}>
|
||||
{}
|
||||
<a
|
||||
onClick={(e) => changeTheme(e, item)}
|
||||
className={`${theme === item ? 'active' : ''}`}
|
||||
>
|
||||
<span className="opacity-60 capitalize">
|
||||
{item === 'light'
|
||||
? 'Light'
|
||||
: item === 'dark'
|
||||
? 'Dark'
|
||||
: item === themeConfig.defaultTheme
|
||||
? 'Default'
|
||||
: item}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="toggle toggle-primary"
|
||||
checked={isDark}
|
||||
onChange={() => applyTheme(isDark ? 'light' : 'dark')}
|
||||
aria-label={
|
||||
isDark ? 'Switch to light theme' : 'Switch to dark theme'
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user