diff --git a/.storybook/config.js b/.storybook/config.js
index 23584c9ebe37..9bd434504d35 100644
--- a/.storybook/config.js
+++ b/.storybook/config.js
@@ -5,6 +5,7 @@ import classnames from 'classnames';
import * as styles from './styles.scss';
import messages from '../_locales/en/messages.json';
import { I18n } from '../sticker-creator/util/i18n';
+import { ThemedProvider } from '../ts/components/PopperRootContext';
addDecorator(withKnobs);
@@ -14,9 +15,13 @@ addDecorator((storyFn /* , context */) => {
return (
{contents}
-
- {contents}
-
+
+
+ {contents}
+
+
);
});
diff --git a/package.json b/package.json
index 08e7ffdf1567..8d1b20f1e177 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
"styleguide": "styleguidist server",
"ready": "yarn clean-transpile && yarn grunt && yarn lint && yarn test-node && yarn test-electron && yarn lint-deps",
"dev": "run-p --print-label dev:*",
+ "dev:grunt": "yarn grunt dev",
"dev:webpack": "NODE_ENV=development webpack-dev-server --hot",
"dev:typed-scss": "yarn build:typed-scss -w",
"dev:storybook": "start-storybook -p 6006 -s ./",
diff --git a/sticker-creator/components/StickerFrame.tsx b/sticker-creator/components/StickerFrame.tsx
index 8c4b928c67d3..3c4386aa4c57 100644
--- a/sticker-creator/components/StickerFrame.tsx
+++ b/sticker-creator/components/StickerFrame.tsx
@@ -17,6 +17,7 @@ import {
Props as EmojiPickerProps,
} from '../../ts/components/emoji/EmojiPicker';
import { Emoji } from '../../ts/components/emoji/Emoji';
+import { PopperRootContext } from '../../ts/components/PopperRootContext';
import { useI18n } from '../util/i18n';
export type Mode = 'removable' | 'pick-emoji' | 'add';
@@ -117,12 +118,13 @@ export const StickerFrame = React.memo(
[timerRef]
);
+ const { createRoot, removeRoot } = React.useContext(PopperRootContext);
+
// Create popper root and handle outside clicks
React.useEffect(() => {
if (emojiPickerOpen) {
- const root = document.createElement('div');
+ const root = createRoot();
setEmojiPopperRoot(root);
- document.body.appendChild(root);
const handleOutsideClick = ({ target }: MouseEvent) => {
if (!root.contains(target as Node)) {
setEmojiPickerOpen(false);
@@ -131,27 +133,39 @@ export const StickerFrame = React.memo(
document.addEventListener('click', handleOutsideClick);
return () => {
- document.body.removeChild(root);
+ removeRoot(root);
document.removeEventListener('click', handleOutsideClick);
};
}
return noop;
- }, [emojiPickerOpen, setEmojiPickerOpen, setEmojiPopperRoot]);
+ }, [
+ createRoot,
+ emojiPickerOpen,
+ removeRoot,
+ setEmojiPickerOpen,
+ setEmojiPopperRoot,
+ ]);
React.useEffect(() => {
if (mode !== 'pick-emoji' && image && previewActive) {
- const root = document.createElement('div');
+ const root = createRoot();
setPreviewPopperRoot(root);
- document.body.appendChild(root);
return () => {
- document.body.removeChild(root);
+ removeRoot(root);
};
}
return noop;
- }, [mode, image, previewActive, setPreviewPopperRoot]);
+ }, [
+ createRoot,
+ image,
+ mode,
+ previewActive,
+ removeRoot,
+ setPreviewPopperRoot,
+ ]);
const [dragActive, setDragActive] = React.useState(false);
const containerClass = dragActive ? styles.dragActive : styles.container;
diff --git a/ts/components/PopperRootContext.tsx b/ts/components/PopperRootContext.tsx
new file mode 100644
index 000000000000..2a58014cf93f
--- /dev/null
+++ b/ts/components/PopperRootContext.tsx
@@ -0,0 +1,40 @@
+import * as React from 'react';
+
+const makeApi = (themes?: Array) => ({
+ createRoot: () => {
+ const div = document.createElement('div');
+
+ if (themes) {
+ themes.forEach(theme => {
+ div.classList.add(`${theme}-theme`);
+ });
+ }
+
+ document.body.appendChild(div);
+
+ return div;
+ },
+ removeRoot: (root: HTMLElement) => {
+ document.body.removeChild(root);
+ },
+});
+
+export const PopperRootContext = React.createContext(makeApi());
+
+export type ThemedProviderProps = {
+ themes?: Array;
+ children?: React.ReactChildren;
+};
+
+export const ThemedProvider: React.FunctionComponent = ({
+ themes,
+ children,
+}) => {
+ const api = React.useMemo(() => makeApi(themes), [themes]);
+
+ return (
+
+ {children}
+
+ );
+};