import type { ButtonProps, TooltipProps } from 'antd'; import type { CSSProperties } from 'react'; import ButtonIcon from '@/components/ButtonIcon'; import { ThemeContext, icons } from './themeContext'; interface Props { className?: string; /** Show tooltip */ showTooltip?: boolean; style?: CSSProperties; /** Tooltip placement */ tooltipPlacement?: TooltipProps['placement']; } const DEFAULT_ANIMATION_DURATION = 400; const DEFAULT_ANIMATION_EASING = 'ease-out'; const ThemeSchemaSwitch: FC = memo(({ showTooltip = true, tooltipPlacement = 'bottom', ...props }) => { const { t } = useTranslation(); const { darkMode, themeScheme, toggleThemeScheme } = useContext(ThemeContext); const tooltipContent = showTooltip ? t('icon.themeSchema') : ''; const toggleDark: ButtonProps['onClick'] = event => { const isAppearanceTransition = !window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (!isAppearanceTransition) { toggleThemeScheme(); return; } const transition = document.startViewTransition(() => { toggleThemeScheme(); }); if (themeScheme === 'system') return; const x = event.clientX; const y = event.clientY; const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); transition.ready.then(() => { const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`]; document.documentElement.animate( { clipPath: darkMode ? [...clipPath].reverse() : clipPath }, { duration: DEFAULT_ANIMATION_DURATION, easing: DEFAULT_ANIMATION_EASING, pseudoElement: darkMode ? '::view-transition-old(root)' : '::view-transition-new(root)' } ); }); }; return ( ); }); export default ThemeSchemaSwitch;