Rework the storybook
This commit is contained in:
@ -1,32 +0,0 @@
|
||||
import { Meta } from "@storybook/addon-docs";
|
||||
import screenshotPngUrl from "./screenshot.png";
|
||||
|
||||
<Meta
|
||||
title="account-spa/index.ftl"
|
||||
parameters={{
|
||||
"viewMode": "docs",
|
||||
"previewTabs": {
|
||||
"canvas": { "hidden": true },
|
||||
"zoom": { "hidden": true },
|
||||
"storybook/background": { "hidden": true },
|
||||
"storybook/viewport": { "hidden": true },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<div style={{ "margin": "0 auto", "maxWidth": "700px", "textAlign": "center" }}>
|
||||
|
||||
<p>
|
||||
|
||||
Keycloakify offers two option for creating an account theme:
|
||||
[Multi Page](https://storybook.keycloakify.dev/?path=/story/account-account-ftl--default) or Single Page (also known as Account v3).
|
||||
Since the account Single Page does not support Storybook, here is a screenshot of it's default look:
|
||||
|
||||
<img width="1508" alt="image" src={screenshotPngUrl} />
|
||||
|
||||
[Learn more](https://docs.keycloakify.dev/account-theme)
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
94
stories/account-spa/index.stories.tsx
Normal file
94
stories/account-spa/index.stories.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import React from "react";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { useInsertLinkTags } from "../../dist/tools/useInsertLinkTags";
|
||||
import { tss } from "../tss";
|
||||
// @ts-expect-error
|
||||
import screenshotPngUrl from "./screenshot.png";
|
||||
|
||||
const meta = {
|
||||
title: "Account SPA/index.ftl"
|
||||
} satisfies Meta<any>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const NotInStorybookButSupported: Story = {
|
||||
render: () => <AccountSpa />
|
||||
};
|
||||
|
||||
function AccountSpa() {
|
||||
console.log(window.location.href);
|
||||
|
||||
useInsertLinkTags({
|
||||
componentOrHookName: "Template",
|
||||
hrefs: []
|
||||
});
|
||||
|
||||
const { classes, theme } = useStyles();
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<div className={classes.content}>
|
||||
<p>
|
||||
Keycloakify offers two option for creating an account theme:{" "}
|
||||
<a href="https://docs.keycloakify.dev/account-theme#multi-page" target="_blank">
|
||||
Multi Page
|
||||
</a>{" "}
|
||||
or{" "}
|
||||
<a href="https://docs.keycloakify.dev/account-theme#single-page" target="_blank">
|
||||
Single Page
|
||||
</a>
|
||||
. Since the account Single Page does not support Storybook, here is a screenshot of it's default look:
|
||||
<br />
|
||||
<br />
|
||||
<img className={classes.screenshot} alt="image" src={screenshotPngUrl} />
|
||||
<br />
|
||||
<a href="https://docs.keycloakify.dev/account-theme" target="_blank">
|
||||
Learn more
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = tss.withName({ AccountSpa }).create(({ isDark, theme }) => ({
|
||||
root: {
|
||||
height: "100vh",
|
||||
color: isDark ? "white" : "black",
|
||||
backgroundColor: theme.appContentBg,
|
||||
fontFamily: "'Work Sans'",
|
||||
fontSize: "14px",
|
||||
lineHeight: "24px",
|
||||
WebkitFontSmoothing: "antialiased",
|
||||
"& a": {
|
||||
color: theme.colorSecondary,
|
||||
textDecoration: "none",
|
||||
"&:hover": {
|
||||
textDecoration: "underline"
|
||||
}
|
||||
},
|
||||
"& h1": {
|
||||
fontSize: "32px",
|
||||
marginBottom: 35
|
||||
},
|
||||
display: "flex",
|
||||
justifyContent: "center"
|
||||
},
|
||||
content: {
|
||||
maxWidth: 750,
|
||||
textAlign: "center",
|
||||
marginTop: 100
|
||||
},
|
||||
keycloakifyLogoWrapper: {
|
||||
display: "flex",
|
||||
justifyContent: "center"
|
||||
},
|
||||
keycloakifyLogo: {
|
||||
width: 400
|
||||
},
|
||||
screenshot: {
|
||||
maxWidth: "100%"
|
||||
}
|
||||
}));
|
@ -2,18 +2,20 @@ import React from "react";
|
||||
import { memo, useState } from "react";
|
||||
import { useConstCallback } from "powerhooks";
|
||||
import { keyframes } from "tss-react";
|
||||
// @ts-expect-error
|
||||
import keycloakifyLogoHeroMovingPngUrl from "./keycloakify-logo-hero-moving.png";
|
||||
// @ts-expect-error
|
||||
import keycloakifyLogoHeroStillPngUrl from "./keycloakify-logo-hero-still.png";
|
||||
import { makeStyles } from "./tss";
|
||||
import { tss } from "../tss";
|
||||
|
||||
export type Props = {
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
id?: string;
|
||||
onLoad?: () => void;
|
||||
};
|
||||
|
||||
export const KeycloakifyRotatingLogo = memo((props: Props) => {
|
||||
const { id, style, onLoad: onLoadProp } = props;
|
||||
const { id, className, onLoad: onLoadProp } = props;
|
||||
|
||||
const [isImageLoaded, setIsImageLoaded] = useState(false);
|
||||
|
||||
@ -22,40 +24,41 @@ export const KeycloakifyRotatingLogo = memo((props: Props) => {
|
||||
onLoadProp?.();
|
||||
});
|
||||
|
||||
const { classes } = useStyles({
|
||||
const { cx, classes } = useStyles({
|
||||
isImageLoaded
|
||||
});
|
||||
return (
|
||||
<div id={id} className={classes.root} style={style}>
|
||||
<div id={id} className={cx(classes.root, className)}>
|
||||
<img className={classes.rotatingImg} onLoad={onLoad} src={keycloakifyLogoHeroMovingPngUrl} alt={"Rotating react logo"} />
|
||||
<img className={classes.stillImg} src={keycloakifyLogoHeroStillPngUrl} alt={"keyhole"} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const useStyles = makeStyles<{ isImageLoaded: boolean }>({
|
||||
name: { KeycloakifyRotatingLogo }
|
||||
})((_theme, { isImageLoaded }) => ({
|
||||
root: {
|
||||
position: "relative"
|
||||
},
|
||||
rotatingImg: {
|
||||
animation: `${keyframes({
|
||||
from: {
|
||||
transform: "rotate(0deg)"
|
||||
},
|
||||
to: {
|
||||
transform: "rotate(360deg)"
|
||||
}
|
||||
})} infinite 20s linear`,
|
||||
width: isImageLoaded ? "100%" : undefined,
|
||||
height: isImageLoaded ? "auto" : undefined
|
||||
},
|
||||
stillImg: {
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
width: isImageLoaded ? "100%" : undefined,
|
||||
height: isImageLoaded ? "auto" : undefined
|
||||
}
|
||||
}));
|
||||
const useStyles = tss
|
||||
.withParams<{ isImageLoaded: boolean }>()
|
||||
.withName({ KeycloakifyRotatingLogo })
|
||||
.create(({ isImageLoaded }) => ({
|
||||
root: {
|
||||
position: "relative"
|
||||
},
|
||||
rotatingImg: {
|
||||
animation: `${keyframes({
|
||||
from: {
|
||||
transform: "rotate(0deg)"
|
||||
},
|
||||
to: {
|
||||
transform: "rotate(360deg)"
|
||||
}
|
||||
})} infinite 20s linear`,
|
||||
width: isImageLoaded ? "100%" : undefined,
|
||||
height: isImageLoaded ? "auto" : undefined
|
||||
},
|
||||
stillImg: {
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
width: isImageLoaded ? "100%" : undefined,
|
||||
height: isImageLoaded ? "auto" : undefined
|
||||
}
|
||||
}));
|
||||
|
@ -1,32 +0,0 @@
|
||||
import { Meta } from "@storybook/addon-docs";
|
||||
import { KeycloakifyRotatingLogo } from "./KeycloakifyRotatingLogo";
|
||||
|
||||
<Meta
|
||||
title="Introduction"
|
||||
parameters={{
|
||||
"viewMode": "docs",
|
||||
"previewTabs": {
|
||||
"canvas": { "hidden": true },
|
||||
"zoom": { "hidden": true },
|
||||
"storybook/background": { "hidden": true },
|
||||
"storybook/viewport": { "hidden": true },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<div style={{ "margin": "0 auto", "maxWidth": "700px", "textAlign": "center" }}>
|
||||
<div style={{ "display": "flex", "justifyContent": "center" }}>
|
||||
<KeycloakifyRotatingLogo style={{ "width": 400 }} />
|
||||
</div>
|
||||
<h1><a href="#">Keycloakify </a> Storybook</h1>
|
||||
|
||||
<p>
|
||||
|
||||
This website showcases all the Keycloak user-facing pages of the login and account theme.
|
||||
The storybook serves as a reference to help you determine which pages you would like to personalize.
|
||||
These pages are a direct React adaptation of the [built-in FreeMarker Keycloak pages](https://github.com/keycloak/keycloak/tree/24.0.4/themes/src/main/resources/theme/base).
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
90
stories/intro/intro.stories.tsx
Normal file
90
stories/intro/intro.stories.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import React from "react";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { KeycloakifyRotatingLogo } from "./KeycloakifyRotatingLogo";
|
||||
import { useInsertLinkTags } from "../../dist/tools/useInsertLinkTags";
|
||||
import { useOnFistMount } from "../../dist/tools/useOnFirstMount";
|
||||
import { tss } from "../tss";
|
||||
|
||||
const meta = {
|
||||
title: "Introduction"
|
||||
} satisfies Meta<any>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const WhatIsThisWebsite: Story = {
|
||||
render: () => <Introduction />
|
||||
};
|
||||
|
||||
function Introduction() {
|
||||
console.log(window.location.href);
|
||||
|
||||
useInsertLinkTags({
|
||||
componentOrHookName: "Template",
|
||||
hrefs: []
|
||||
});
|
||||
|
||||
const { classes, theme } = useStyles();
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<div className={classes.content}>
|
||||
<div className={classes.keycloakifyLogoWrapper}>
|
||||
<KeycloakifyRotatingLogo className={classes.keycloakifyLogo} />
|
||||
</div>
|
||||
<h1>
|
||||
<a href={theme.brandUrl}>Keycloakify </a> Storybook
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
This website showcases all the Keycloak user-facing pages of the Login and{" "}
|
||||
<a href="https://docs.keycloakify.dev/account-theme#multi-page">Account Multi-Page theme</a>.<br />
|
||||
The storybook serves as a reference to help you determine which pages you would like to personalize.
|
||||
<br />
|
||||
These pages are a direct React adaptation of the{" "}
|
||||
<a href="https://github.com/keycloak/keycloak/tree/24.0.4/themes/src/main/resources/theme/base" target="_blank">
|
||||
built-in FreeMarker Keycloak pages
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = tss.withName({ Introduction }).create(({ isDark, theme }) => ({
|
||||
root: {
|
||||
height: "100vh",
|
||||
color: isDark ? "white" : "black",
|
||||
backgroundColor: theme.appContentBg,
|
||||
fontFamily: "'Work Sans'",
|
||||
fontSize: "14px",
|
||||
lineHeight: "24px",
|
||||
WebkitFontSmoothing: "antialiased",
|
||||
"& a": {
|
||||
color: theme.colorSecondary,
|
||||
textDecoration: "none",
|
||||
"&:hover": {
|
||||
textDecoration: "underline"
|
||||
}
|
||||
},
|
||||
"& h1": {
|
||||
fontSize: "32px",
|
||||
marginBottom: 35
|
||||
},
|
||||
display: "flex",
|
||||
justifyContent: "center"
|
||||
},
|
||||
content: {
|
||||
maxWidth: 750,
|
||||
textAlign: "center"
|
||||
},
|
||||
keycloakifyLogoWrapper: {
|
||||
display: "flex",
|
||||
justifyContent: "center"
|
||||
},
|
||||
keycloakifyLogo: {
|
||||
width: 400
|
||||
}
|
||||
}));
|
@ -1,5 +0,0 @@
|
||||
import { createMakeAndWithStyles } from "tss-react";
|
||||
|
||||
export const { makeStyles, useStyles } = createMakeAndWithStyles({
|
||||
useTheme: () => ({})
|
||||
});
|
13
stories/tss.ts
Normal file
13
stories/tss.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { createTss } from "tss-react";
|
||||
import { useDarkMode } from "storybook-dark-mode";
|
||||
import { darkTheme, lightTheme } from "../.storybook/customTheme";
|
||||
|
||||
function useContext() {
|
||||
const isDark = useDarkMode();
|
||||
|
||||
return { isDark, theme: isDark ? darkTheme : lightTheme };
|
||||
}
|
||||
|
||||
export const { tss } = createTss({
|
||||
useContext
|
||||
});
|
Reference in New Issue
Block a user