Address white falshes in storybook

This commit is contained in:
Joseph Garrone 2024-06-05 01:02:17 +02:00
parent 183826ca0d
commit 0b5a7544ca
5 changed files with 93 additions and 100 deletions

View File

@ -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}
</>
);

View 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>

View File

@ -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 };

View File

@ -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("---");
}

View File

@ -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