feat: custom org brand color (#474)
* feat: add package * feat: add a new color picker * feat: integrate with supabase * feat: add translation * run translation script * feat: hover state * quick fix * fix: requested PR fixes * update lock * ux improvements * remove log * cleanup and improve code --------- Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
co-authored by
Rotimi Best
parent
1ee02cdf3a
commit
947181a3c5
@@ -1,14 +1,117 @@
|
||||
export function setTheme(theme?: string) {
|
||||
// In case the default theme is added but another theme exists
|
||||
if (!theme && document.body.className.includes('theme-')) {
|
||||
const regex = /theme-[\w]+/gi;
|
||||
document.body.className = document.body.className.replace(regex, theme || '');
|
||||
import { tc } from '$lib/utils/functions/trycatch';
|
||||
import { darken, lighten } from 'color2k';
|
||||
|
||||
function updateThemeClassInBody(newClass: string, customRegex?: string) {
|
||||
const regex = /theme-[\w]+/gi;
|
||||
document.body.className = document.body.className.replace(customRegex ?? regex, newClass);
|
||||
}
|
||||
|
||||
export function setTheme(theme: string) {
|
||||
const _theme = theme || '';
|
||||
|
||||
// this condition checks if it's a hex code from the db or a specified theme
|
||||
if (theme && !theme.includes('theme-')) {
|
||||
// add the "custom-theme" styles to the head tag
|
||||
injectCustomTheme(theme);
|
||||
|
||||
// add the "custom-theme" classname to the head tag
|
||||
setCustomTheme('theme-custom');
|
||||
} else if (!theme && document.body.className.includes('theme-')) {
|
||||
// if no theme and a theme is already applied, remove it
|
||||
updateThemeClassInBody(_theme);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// In case theme already exists in dom, don't add
|
||||
if (document.body.className.includes(theme || '')) return;
|
||||
if (document.body.className.includes(_theme)) return;
|
||||
|
||||
localStorage.setItem('theme', theme || '');
|
||||
document.body.className = document.body.className.concat(' ', theme || '');
|
||||
// set the new theme
|
||||
localStorage.setItem('theme', _theme);
|
||||
document.body.className = document.body.className.concat(' ', _theme);
|
||||
}
|
||||
|
||||
export function setCustomTheme(theme?: string) {
|
||||
// In case the default theme is added but another theme exists
|
||||
if (!theme && document.body.className.includes('theme-')) {
|
||||
updateThemeClassInBody(theme || '');
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any class starting with "theme-"
|
||||
updateThemeClassInBody('');
|
||||
|
||||
const _theme = theme || '';
|
||||
// Add the new theme if it doesn't already exist
|
||||
if (!document.body.className.includes(_theme)) {
|
||||
localStorage.setItem('theme', _theme);
|
||||
document.body.className = document.body.className.concat(' ', _theme);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle this functions in a try catch if hex is not valid.
|
||||
const _lighten = (hex: string, no: number) => tc(() => lighten(hex, no), hex);
|
||||
const _darken = (hex: string, no: number) => tc(() => darken(hex, no), hex);
|
||||
|
||||
export function injectCustomTheme(hex: string) {
|
||||
const styleId = 'theme-custom';
|
||||
let styleElement = document.getElementById(styleId);
|
||||
|
||||
// generate shades using color2k's lighten function
|
||||
const shades = {
|
||||
50: _lighten(hex, 0.7),
|
||||
100: _lighten(hex, 0.6),
|
||||
200: _lighten(hex, 0.5),
|
||||
300: _lighten(hex, 0.4),
|
||||
400: _lighten(hex, 0.3),
|
||||
500: _lighten(hex, 0.2),
|
||||
600: _lighten(hex, 0.1),
|
||||
700: hex,
|
||||
800: _darken(hex, 0.1),
|
||||
900: _darken(hex, 0.2)
|
||||
};
|
||||
|
||||
const styleContent = `
|
||||
.theme-custom .bg-primary-50 { background-color: ${shades[50]} !important; }
|
||||
.theme-custom .bg-primary-100 { background-color: ${shades[100]} !important; }
|
||||
.theme-custom .bg-primary-200 { background-color: ${shades[200]} !important; }
|
||||
.theme-custom .bg-primary-300 { background-color: ${shades[300]} !important; }
|
||||
.theme-custom .bg-primary-400 { background-color: ${shades[400]} !important; }
|
||||
.theme-custom .bg-primary-500 { background-color: ${shades[500]} !important; }
|
||||
.theme-custom .bg-primary-600 { background-color: ${shades[600]} !important; }
|
||||
.theme-custom .bg-primary-700 { background-color: ${shades[700]} !important; }
|
||||
.theme-custom .bg-primary-800 { background-color: ${shades[800]} !important; }
|
||||
.theme-custom .bg-primary-900 { background-color: ${shades[900]} !important; }
|
||||
|
||||
.theme-custom .text-primary-50 { color: ${shades[50]} !important; }
|
||||
.theme-custom .text-primary-100 { color: ${shades[100]} !important; }
|
||||
.theme-custom .text-primary-200 { color: ${shades[200]} !important; }
|
||||
.theme-custom .text-primary-300 { color: ${shades[300]} !important; }
|
||||
.theme-custom .text-primary-400 { color: ${shades[400]} !important; }
|
||||
.theme-custom .text-primary-500 { color: ${shades[500]} !important; }
|
||||
.theme-custom .text-primary-600 { color: ${shades[600]} !important; }
|
||||
.theme-custom .text-primary-700 { color: ${shades[700]} !important; }
|
||||
.theme-custom .text-primary-800 { color: ${shades[800]} !important; }
|
||||
.theme-custom .text-primary-900 { color: ${shades[900]} !important; }
|
||||
|
||||
.theme-custom .border-primary-50 { border-color: ${shades[50]} !important; }
|
||||
.theme-custom .border-primary-100 { border-color: ${shades[100]} !important; }
|
||||
.theme-custom .border-primary-200 { border-color: ${shades[200]} !important; }
|
||||
.theme-custom .border-primary-300 { border-color: ${shades[300]} !important; }
|
||||
.theme-custom .border-primary-400 { border-color: ${shades[400]} !important; }
|
||||
.theme-custom .border-primary-500 { border-color: ${shades[500]} !important; }
|
||||
.theme-custom .border-primary-600 { border-color: ${shades[600]} !important; }
|
||||
.theme-custom .border-primary-700 { border-color: ${shades[700]} !important; }
|
||||
.theme-custom .border-primary-800 { border-color: ${shades[800]} !important; }
|
||||
.theme-custom .border-primary-900 { border-color: ${shades[900]} !important; }
|
||||
`;
|
||||
|
||||
if (styleElement) {
|
||||
styleElement.innerHTML = styleContent;
|
||||
} else {
|
||||
styleElement = document.createElement('style');
|
||||
styleElement.id = styleId;
|
||||
styleElement.innerHTML = styleContent;
|
||||
document.head.appendChild(styleElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
export function tc<T>(tryFunc: () => T, catchFunc: T | ((e?: Error) => T)) {
|
||||
let val: T;
|
||||
try {
|
||||
val = tryFunc();
|
||||
} catch (e: unknown) {
|
||||
if (typeof catchFunc === 'function') {
|
||||
// @ts-ignore
|
||||
val = catchFunc(e);
|
||||
} else {
|
||||
val = catchFunc;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
Reference in New Issue
Block a user