Address white falshes in storybook
This commit is contained in:
parent
183826ca0d
commit
0b5a7544ca
@ -34,7 +34,6 @@ export function DocsContainer({ children, context }) {
|
||||
.docblock-argstable-head th:nth-child(3), .docblock-argstable-body tr > td:nth-child(2) p {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
<BaseContainer
|
||||
context={{
|
||||
@ -62,20 +61,8 @@ export function DocsContainer({ children, context }) {
|
||||
|
||||
export function CanvasContainer({ children }) {
|
||||
|
||||
const isStorybookUiDark = useDarkMode();
|
||||
|
||||
const theme = isStorybookUiDark ? darkTheme : lightTheme;
|
||||
|
||||
const backgroundColor = theme.appBg;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{`
|
||||
body {
|
||||
padding: 0 !important;
|
||||
background-color: ${backgroundColor};
|
||||
}
|
||||
`}</style>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
|
15
.storybook/preview-head.html
Normal file
15
.storybook/preview-head.html
Normal file
@ -0,0 +1,15 @@
|
||||
<style>
|
||||
body {
|
||||
padding: 0 !important;
|
||||
background-color: #393939 !important;
|
||||
}
|
||||
|
||||
body.sb-show-preparing-docs>.sb-wrapper {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
body .sb-preparing-story {
|
||||
visibility: hidden;
|
||||
|
||||
}
|
||||
</style>
|
@ -1,86 +1,68 @@
|
||||
import { useReducer, useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
createStatefulObservable,
|
||||
useRerenderOnChange
|
||||
} from "keycloakify/tools/StatefulObservable";
|
||||
|
||||
/**
|
||||
* NOTE: The component that use this hook can only be mounded once!
|
||||
* And can't rerender with different hrefs.
|
||||
* If it's mounted again the page will be reloaded.
|
||||
* This simulates the behavior of a server rendered page that imports css stylesheet in the head.
|
||||
*/
|
||||
export function createUseInsertLinkTags() {
|
||||
let linkTagsContext:
|
||||
| {
|
||||
styleSheetHrefs: string[];
|
||||
prAreAllStyleSheetsLoaded: Promise<void>;
|
||||
remove: () => void;
|
||||
}
|
||||
| undefined = undefined;
|
||||
let isFistMount = true;
|
||||
|
||||
const obsAreAllStyleSheetsLoaded = createStatefulObservable(() => false);
|
||||
|
||||
/** NOTE: The hrefs can't changes. There should be only one one call on this. */
|
||||
function useInsertLinkTags(params: { hrefs: string[] }) {
|
||||
const { hrefs } = params;
|
||||
|
||||
const [areAllStyleSheetsLoaded, setAllStyleSheetLoaded] = useReducer(
|
||||
() => true,
|
||||
hrefs.length === 0
|
||||
);
|
||||
useRerenderOnChange(obsAreAllStyleSheetsLoaded);
|
||||
|
||||
useState(() => {
|
||||
if (!isFistMount) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
isFistMount = false;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let isActive = true;
|
||||
|
||||
mount_link_tags: {
|
||||
if (linkTagsContext !== undefined) {
|
||||
if (
|
||||
JSON.stringify(linkTagsContext.styleSheetHrefs) ===
|
||||
JSON.stringify(hrefs)
|
||||
) {
|
||||
break mount_link_tags;
|
||||
}
|
||||
let lastMountedHtmlElement: HTMLLinkElement | undefined = undefined;
|
||||
|
||||
linkTagsContext.remove();
|
||||
const prs: Promise<void>[] = [];
|
||||
|
||||
linkTagsContext = undefined;
|
||||
for (const href of hrefs) {
|
||||
const htmlElement = document.createElement("link");
|
||||
|
||||
prs.push(
|
||||
new Promise<void>(resolve =>
|
||||
htmlElement.addEventListener("load", () => resolve())
|
||||
)
|
||||
);
|
||||
|
||||
htmlElement.rel = "stylesheet";
|
||||
|
||||
htmlElement.href = href;
|
||||
|
||||
if (lastMountedHtmlElement !== undefined) {
|
||||
lastMountedHtmlElement.insertAdjacentElement("afterend", htmlElement);
|
||||
} else {
|
||||
document.head.prepend(htmlElement);
|
||||
}
|
||||
|
||||
let lastMountedHtmlElement: HTMLLinkElement | undefined = undefined;
|
||||
|
||||
const prs: Promise<void>[] = [];
|
||||
const removeFns: (() => void)[] = [];
|
||||
|
||||
for (const href of hrefs) {
|
||||
const htmlElement = document.createElement("link");
|
||||
|
||||
prs.push(
|
||||
new Promise<void>(resolve =>
|
||||
htmlElement.addEventListener("load", () => resolve())
|
||||
)
|
||||
);
|
||||
|
||||
htmlElement.rel = "stylesheet";
|
||||
|
||||
htmlElement.href = href;
|
||||
|
||||
if (lastMountedHtmlElement !== undefined) {
|
||||
lastMountedHtmlElement.insertAdjacentElement(
|
||||
"afterend",
|
||||
htmlElement
|
||||
);
|
||||
} else {
|
||||
document.head.prepend(htmlElement);
|
||||
}
|
||||
|
||||
removeFns.push(() => {
|
||||
htmlElement.remove();
|
||||
});
|
||||
|
||||
lastMountedHtmlElement = htmlElement;
|
||||
}
|
||||
|
||||
linkTagsContext = {
|
||||
styleSheetHrefs: hrefs,
|
||||
prAreAllStyleSheetsLoaded: Promise.all(prs).then(() => undefined),
|
||||
remove: () => removeFns.forEach(fn => fn())
|
||||
};
|
||||
lastMountedHtmlElement = htmlElement;
|
||||
}
|
||||
|
||||
linkTagsContext.prAreAllStyleSheetsLoaded.then(() => {
|
||||
Promise.all(prs).then(() => {
|
||||
if (!isActive) {
|
||||
return;
|
||||
}
|
||||
setAllStyleSheetLoaded();
|
||||
obsAreAllStyleSheetsLoaded.current = true;
|
||||
});
|
||||
|
||||
return () => {
|
||||
@ -88,7 +70,7 @@ export function createUseInsertLinkTags() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { areAllStyleSheetsLoaded };
|
||||
return { areAllStyleSheetsLoaded: obsAreAllStyleSheetsLoaded.current };
|
||||
}
|
||||
|
||||
return { useInsertLinkTags };
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import { assert } from "tsafe/assert";
|
||||
|
||||
export type ScriptTag = ScriptTag.TextContent | ScriptTag.Src;
|
||||
@ -16,20 +16,28 @@ export namespace ScriptTag {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: The component that use this hook can only be mounded once!
|
||||
* And can'r rerender with different scriptTags.
|
||||
* If it's mounted again the page will be reloaded.
|
||||
* This simulates the behavior of a server rendered page that imports javascript in the head.
|
||||
*/
|
||||
export function createUseInsertScriptTags() {
|
||||
let areScriptsInserted = false;
|
||||
|
||||
let scriptTagsFingerprint: string | undefined;
|
||||
let isFistMount = true;
|
||||
|
||||
function useInsertScriptTags(params: { scriptTags: ScriptTag[] }) {
|
||||
const { scriptTags } = params;
|
||||
|
||||
if (scriptTagsFingerprint === undefined) {
|
||||
scriptTagsFingerprint = getScriptTagsFingerprint(scriptTags);
|
||||
} else if (getScriptTagsFingerprint(scriptTags) !== scriptTagsFingerprint) {
|
||||
// NOTE: This is for storybook, when we switch to a page that has different scripts.
|
||||
window.location.reload();
|
||||
}
|
||||
useState(() => {
|
||||
if (!isFistMount) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
isFistMount = false;
|
||||
});
|
||||
|
||||
const insertScriptTags = useCallback(() => {
|
||||
if (areScriptsInserted) {
|
||||
@ -85,17 +93,3 @@ export function createUseInsertScriptTags() {
|
||||
|
||||
return { useInsertScriptTags };
|
||||
}
|
||||
|
||||
function getScriptTagsFingerprint(scriptTags: ScriptTag[]) {
|
||||
return scriptTags
|
||||
.map((scriptTag): string => {
|
||||
if ("textContent" in scriptTag) {
|
||||
return scriptTag.textContent;
|
||||
}
|
||||
if ("src" in scriptTag) {
|
||||
return scriptTag.src;
|
||||
}
|
||||
assert(false);
|
||||
})
|
||||
.join("---");
|
||||
}
|
||||
|
@ -76,6 +76,21 @@ export const WithRecaptcha: Story = {
|
||||
)
|
||||
};
|
||||
|
||||
export const WithRecaptchaFrench: Story = {
|
||||
render: () => (
|
||||
<PageStory
|
||||
kcContext={{
|
||||
locale: {
|
||||
currentLanguageTag: "fr"
|
||||
},
|
||||
scripts: ["https://www.google.com/recaptcha/api.js?hl=fr"],
|
||||
recaptchaRequired: true,
|
||||
recaptchaSiteKey: "6LfQHvApAAAAAE73SYTd5vS0lB1Xr7zdiQ-6iBVa"
|
||||
}}
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
||||
export const WithPresets: Story = {
|
||||
render: () => (
|
||||
<PageStory
|
||||
|
Loading…
x
Reference in New Issue
Block a user