chore(core-theming): improve theme change behavior

This commit is contained in:
Wroud
2020-09-23 01:37:42 +03:00
parent 3c144c7bab
commit b153d9ab68
4 changed files with 31 additions and 13 deletions
+10 -1
View File
@@ -7,6 +7,7 @@
*/
import { observer } from 'mobx-react';
import { useRef, useLayoutEffect } from 'react';
import styled, { css } from 'reshadow';
import { useService } from '@cloudbeaver/core-di';
@@ -24,11 +25,19 @@ const bodyStyles = css`
`;
export const Body = observer(function Body() {
const ref = useRef<HTMLDivElement>(null);
const screenService = useService(ScreenService);
const Screen = screenService.screen?.component;
// sync classes from theme with body for popup components and etc
useLayoutEffect(() => {
if (ref.current) {
document.body.className = ref.current.className;
}
});
return styled(useStyles(bodyStyles))(
<theme as="div">
<theme as="div" ref={ref}>
{Screen && <Screen />}
<DialogsPortal />
<Notifications />
@@ -49,7 +49,7 @@ export const TableItemExpand = observer(function TableItemExpand({
}
}, [tableContext, context, onExpand, disabled]);
return styled()(
return styled(styles)(
<table-item-expand-box as='div' className={className} onClick={handleClick}>
<Icon name="angle" viewBox="0 0 15 8" {...use({ expanded: context.isExpanded() })}/>
</table-item-expand-box>
@@ -10,6 +10,6 @@ $theme-class: "theme-#{$theme-name}";
@mixin theme-matcher() {
theme {
composes: #{$theme-class} from global;
composes: #{$theme-class} theme-typography from global;
}
}
+19 -10
View File
@@ -7,7 +7,7 @@
*/
import { useObserver } from 'mobx-react';
import { useMemo, useState } from 'react';
import { useMemo, useRef, useState } from 'react';
import { create } from 'reshadow';
import { useService } from '@cloudbeaver/core-di';
@@ -33,12 +33,19 @@ export function useStyles(
}
// todo do you understand that we store ALL STYLES in each component that uses this hook?
const [loadedStyles, setLoadedStyles] = useState<BaseStyles[]>([]);
const stylesRef = useRef<Array<Style | boolean | undefined>>([]);
const [patch, forceUpdate] = useState(0);
const loadedStyles = useRef<BaseStyles[]>([]);
const themeService = useService(ThemeService);
const currentThemeId = useObserver(() => themeService.currentThemeId);
const filteredStyles = componentStyles.filter(Boolean) as Array<Style>;
useMemo(() => {
let changed = componentStyles.length !== stylesRef.current.length;
for (let i = 0; !changed && i < componentStyles.length; i++) {
changed = stylesRef.current[i] !== componentStyles[i];
}
if (changed) {
const staticStyles: BaseStyles[] = [];
const themedStyles = [];
@@ -51,18 +58,20 @@ export function useStyles(
staticStyles.push(data);
}
}
setLoadedStyles(flat(staticStyles));
loadedStyles.current = flat(staticStyles);
Promise
.all(themedStyles)
.then(styles => setLoadedStyles(flat([staticStyles, styles])));
}, [currentThemeId, ...filteredStyles, filteredStyles.length]);
.then((styles) => {
loadedStyles.current = flat([staticStyles, styles]);
forceUpdate(v => v++);
});
}
const styles = useMemo(() => {
const themeStyles = themeService.getThemeStyles(currentThemeId);
return applyComposes([...themeStyles, ...loadedStyles]);
}, [currentThemeId, ...loadedStyles, loadedStyles.length]);
/* we put dynamic array length as the dependency because of preact bug,
otherwise useMemo will not be triggered on array change */
return applyComposes([...themeStyles, ...loadedStyles.current]);
}, [currentThemeId, patch]);
return create(styles); // todo this method is called in each rerender
}