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 { SanitizedThemeConfig } from '../../interfaces/sanitized-config';
|
||||||
import { LOCAL_STORAGE_KEY_NAME } from '../../constants';
|
import { LOCAL_STORAGE_KEY_NAME } from '../../constants';
|
||||||
import { skeleton } from '../../utils';
|
import { skeleton } from '../../utils';
|
||||||
import { MouseEvent } from 'react';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a theme changer component.
|
* Renders a light/dark theme toggle.
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
*/
|
||||||
const ThemeChanger = ({
|
const ThemeChanger = ({
|
||||||
theme,
|
theme,
|
||||||
setTheme,
|
setTheme,
|
||||||
loading,
|
loading,
|
||||||
themeConfig,
|
|
||||||
}: {
|
}: {
|
||||||
theme: string;
|
theme: string;
|
||||||
setTheme: (theme: string) => void;
|
setTheme: (theme: string) => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
themeConfig: SanitizedThemeConfig;
|
themeConfig: SanitizedThemeConfig;
|
||||||
}) => {
|
}) => {
|
||||||
const changeTheme = (
|
const isDark = theme === 'dark';
|
||||||
e: MouseEvent<HTMLAnchorElement>,
|
|
||||||
selectedTheme: string,
|
|
||||||
) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
document.querySelector('html')?.setAttribute('data-theme', selectedTheme);
|
|
||||||
|
|
||||||
|
const applyTheme = (next: 'light' | 'dark') => {
|
||||||
|
document.querySelector('html')?.setAttribute('data-theme', next);
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
localStorage.setItem(LOCAL_STORAGE_KEY_NAME, selectedTheme);
|
localStorage.setItem(LOCAL_STORAGE_KEY_NAME, next);
|
||||||
|
setTheme(next);
|
||||||
setTheme(selectedTheme);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card overflow-visible shadow-lg card-sm bg-base-100">
|
<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">
|
<div className="flex-1">
|
||||||
<h5 className="card-title">
|
<h5 className="card-title">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
@ -54,65 +39,30 @@ const ThemeChanger = ({
|
|||||||
<span className="text-base-content opacity-70">Theme</span>
|
<span className="text-base-content opacity-70">Theme</span>
|
||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="text-base-content/50 capitalize text-sm">
|
<span className="text-base-content/50 text-sm">
|
||||||
{loading
|
{loading
|
||||||
? skeleton({ widthCls: 'w-16', heightCls: 'h-5' })
|
? skeleton({ widthCls: 'w-16', heightCls: 'h-5' })
|
||||||
: theme === 'light'
|
: isDark
|
||||||
? 'Light'
|
? 'Dark'
|
||||||
: theme === 'dark'
|
: 'Light'}
|
||||||
? 'Dark'
|
|
||||||
: theme === themeConfig.defaultTheme
|
|
||||||
? 'Default'
|
|
||||||
: theme}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-0">
|
<div className="flex-0">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
skeleton({
|
skeleton({
|
||||||
widthCls: 'w-12',
|
widthCls: 'w-12',
|
||||||
heightCls: 'h-10',
|
heightCls: 'h-8',
|
||||||
className: 'mr-6',
|
|
||||||
})
|
})
|
||||||
) : (
|
) : (
|
||||||
<div title="Change Theme" className="dropdown dropdown-end">
|
<input
|
||||||
<div
|
type="checkbox"
|
||||||
tabIndex={0}
|
className="toggle toggle-primary"
|
||||||
className="btn btn-ghost m-1 normal-case opacity-50 text-base-content flex items-center whitespace-nowrap"
|
checked={isDark}
|
||||||
>
|
onChange={() => applyTheme(isDark ? 'light' : 'dark')}
|
||||||
<RiDice4Line className="inline-block w-5 h-5 stroke-current" />
|
aria-label={
|
||||||
</div>
|
isDark ? 'Switch to light theme' : 'Switch to dark theme'
|
||||||
<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>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user