feat: implement light and dark theme (#30)

This commit is contained in:
Dominic Elm
2024-08-08 15:56:36 +02:00
committed by GitHub
parent e8447db417
commit 4b59a79baa
35 changed files with 799 additions and 479 deletions

View File

@@ -8,6 +8,7 @@ interface BaseIconButtonProps {
className?: string;
iconClassName?: string;
disabledClassName?: string;
title?: string;
disabled?: boolean;
onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}
@@ -32,18 +33,20 @@ export const IconButton = memo(
iconClassName,
disabledClassName,
disabled = false,
title,
onClick,
children,
}: IconButtonProps) => {
return (
<button
className={classNames(
'flex items-center text-gray-600 bg-transparent enabled:hover:text-gray-900 rounded-md p-1 enabled:hover:bg-gray-200/80 disabled:cursor-not-allowed',
'flex items-center text-bolt-elements-item-contentDefault bg-transparent enabled:hover:text-bolt-elements-item-contentActive rounded-md p-1 enabled:hover:bg-bolt-elements-item-backgroundActive disabled:cursor-not-allowed',
{
[classNames('opacity-30', disabledClassName)]: disabled,
},
className,
)}
title={title}
disabled={disabled}
onClick={(event) => {
if (disabled) {

View File

@@ -8,7 +8,12 @@ interface PanelHeaderProps {
export const PanelHeader = memo(({ className, children }: PanelHeaderProps) => {
return (
<div className={classNames('flex items-center gap-2 bg-gray-50 border-b px-4 py-1 min-h-[34px]', className)}>
<div
className={classNames(
'flex items-center gap-2 bg-bolt-elements-background-depth-2 text-bolt-elements-textSecondary border-b border-bolt-elements-borderColor px-4 py-1 min-h-[34px] text-sm',
className,
)}
>
{children}
</div>
);

View File

@@ -14,7 +14,7 @@ export const PanelHeaderButton = memo(
return (
<button
className={classNames(
'flex items-center gap-1.5 px-1.5 rounded-md py-0.5 bg-transparent hover:bg-white disabled:cursor-not-allowed',
'flex items-center gap-1.5 px-1.5 rounded-md py-0.5 text-bolt-elements-item-contentDefault bg-transparent enabled:hover:text-bolt-elements-item-contentActive enabled:hover:bg-bolt-elements-item-backgroundActive disabled:cursor-not-allowed',
{
[classNames('opacity-30', disabledClassName)]: disabled,
},

View File

@@ -23,7 +23,7 @@ export const Slider = genericMemo(<T,>({ selected, options, setSelected }: Slide
const isLeftSelected = selected === options.left.value;
return (
<div className="flex items-center flex-wrap gap-1 border rounded-lg p-1">
<div className="flex items-center flex-wrap gap-1 bg-bolt-elements-background-depth-1 rounded-full p-1">
<SliderButton selected={isLeftSelected} setSelected={() => setSelected?.(options.left.value)}>
{options.left.text}
</SliderButton>
@@ -45,8 +45,10 @@ const SliderButton = memo(({ selected, children, setSelected }: SliderButtonProp
<button
onClick={setSelected}
className={classNames(
'bg-transparent text-sm transition-colors px-2.5 py-0.5 rounded-md relative',
selected ? 'text-white' : 'text-gray-600 hover:text-accent-600 hover:bg-accent-600/10',
'bg-transparent text-sm px-2.5 py-0.5 rounded-full relative',
selected
? 'text-bolt-elements-item-contentAccent'
: 'text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive',
)}
>
<span className="relative z-10">{children}</span>
@@ -54,7 +56,7 @@ const SliderButton = memo(({ selected, children, setSelected }: SliderButtonProp
<motion.span
layoutId="pill-tab"
transition={{ type: 'spring', duration: 0.5 }}
className="absolute inset-0 z-0 bg-accent-600 rounded-md"
className="absolute inset-0 z-0 bg-bolt-elements-item-backgroundAccent rounded-full"
></motion.span>
)}
</button>

View File

@@ -0,0 +1,29 @@
import { useStore } from '@nanostores/react';
import { memo, useEffect, useState } from 'react';
import { themeStore, toggleTheme } from '~/lib/stores/theme';
import { IconButton } from './IconButton';
interface ThemeSwitchProps {
className?: string;
}
export const ThemeSwitch = memo(({ className }: ThemeSwitchProps) => {
const theme = useStore(themeStore);
const [domLoaded, setDomLoaded] = useState(false);
useEffect(() => {
setDomLoaded(true);
}, []);
return (
domLoaded && (
<IconButton
className={className}
icon={theme === 'dark' ? 'i-ph-sun-dim-duotone' : 'i-ph-moon-stars-duotone'}
size="xl"
title="Toggle Theme"
onClick={toggleTheme}
/>
)
);
});