Files
cinny/src/app/hooks/useTheme.ts
Ajay Bura 08e975cd8e Change username color in chat with power level color (#2282)
* add active theme context

* add chroma js library

* add hook for accessible tag color

* disable reply user color - temporary

* render user color based on tag in room timeline

* remove default tag icons

* move accessible color function to plugins

* render user power color in reply

* increase username weight in timeline

* add default color for member power level tag

* show red slash in power color badge with no color

* show power level color in room input reply

* show power level username color in notifications

* show power level color in notification reply

* show power level color in message search

* render power level color in room pin menu

* add toggle for legacy username colors

* drop over saturation from member default color

* change border color of power color badge

* show legacy username color in direct rooms
2025-03-23 22:09:29 +11:00

111 lines
3.2 KiB
TypeScript

import { lightTheme } from 'folds';
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { onDarkFontWeight, onLightFontWeight } from '../../config.css';
import { butterTheme, darkTheme, silverTheme } from '../../colors.css';
import { settingsAtom } from '../state/settings';
import { useSetting } from '../state/hooks/settings';
export enum ThemeKind {
Light = 'light',
Dark = 'dark',
}
export type Theme = {
id: string;
kind: ThemeKind;
classNames: string[];
};
export const LightTheme: Theme = {
id: 'light-theme',
kind: ThemeKind.Light,
classNames: [lightTheme, onLightFontWeight, 'prism-light'],
};
export const SilverTheme: Theme = {
id: 'silver-theme',
kind: ThemeKind.Light,
classNames: ['silver-theme', silverTheme, onLightFontWeight, 'prism-light'],
};
export const DarkTheme: Theme = {
id: 'dark-theme',
kind: ThemeKind.Dark,
classNames: ['dark-theme', darkTheme, onDarkFontWeight, 'prism-dark'],
};
export const ButterTheme: Theme = {
id: 'butter-theme',
kind: ThemeKind.Dark,
classNames: ['butter-theme', butterTheme, onDarkFontWeight, 'prism-dark'],
};
export const useThemes = (): Theme[] => {
const themes: Theme[] = useMemo(() => [LightTheme, SilverTheme, DarkTheme, ButterTheme], []);
return themes;
};
export const useThemeNames = (): Record<string, string> =>
useMemo(
() => ({
[LightTheme.id]: 'Light',
[SilverTheme.id]: 'Silver',
[DarkTheme.id]: 'Dark',
[ButterTheme.id]: 'Butter',
}),
[]
);
export const useSystemThemeKind = (): ThemeKind => {
const darkModeQueryList = useMemo(() => window.matchMedia('(prefers-color-scheme: dark)'), []);
const [themeKind, setThemeKind] = useState<ThemeKind>(
darkModeQueryList.matches ? ThemeKind.Dark : ThemeKind.Light
);
useEffect(() => {
const handleMediaQueryChange = () => {
setThemeKind(darkModeQueryList.matches ? ThemeKind.Dark : ThemeKind.Light);
};
darkModeQueryList.addEventListener('change', handleMediaQueryChange);
return () => {
darkModeQueryList.removeEventListener('change', handleMediaQueryChange);
};
}, [darkModeQueryList, setThemeKind]);
return themeKind;
};
export const useActiveTheme = (): Theme => {
const systemThemeKind = useSystemThemeKind();
const themes = useThemes();
const [systemTheme] = useSetting(settingsAtom, 'useSystemTheme');
const [themeId] = useSetting(settingsAtom, 'themeId');
const [lightThemeId] = useSetting(settingsAtom, 'lightThemeId');
const [darkThemeId] = useSetting(settingsAtom, 'darkThemeId');
if (!systemTheme) {
const selectedTheme = themes.find((theme) => theme.id === themeId) ?? LightTheme;
return selectedTheme;
}
const selectedTheme =
systemThemeKind === ThemeKind.Dark
? themes.find((theme) => theme.id === darkThemeId) ?? DarkTheme
: themes.find((theme) => theme.id === lightThemeId) ?? LightTheme;
return selectedTheme;
};
const ThemeContext = createContext<Theme | null>(null);
export const ThemeContextProvider = ThemeContext.Provider;
export const useTheme = (): Theme => {
const theme = useContext(ThemeContext);
if (!theme) {
throw new Error('No theme provided!');
}
return theme;
};