diff --git a/src/components/LoginPageLayout/LoginPageLayout.scss b/src/components/LoginPageLayout/LoginPageLayout.scss new file mode 100644 index 000000000..d9f788ab9 --- /dev/null +++ b/src/components/LoginPageLayout/LoginPageLayout.scss @@ -0,0 +1,19 @@ +@import "vanilla-framework"; + +@media screen and (max-width: $breakpoint-small) { + .page-row { + padding: 0; + } + + .page-card { + border: 0; + } + + .is-paper { + background-color: #fff; + } +} + +.page-inner { + padding: 1rem 2rem 2rem; +} diff --git a/src/components/LoginPageLayout/LoginPageLayout.stories.mdx b/src/components/LoginPageLayout/LoginPageLayout.stories.mdx new file mode 100644 index 000000000..125137c03 --- /dev/null +++ b/src/components/LoginPageLayout/LoginPageLayout.stories.mdx @@ -0,0 +1,103 @@ +import { Meta, ArgsTable, Canvas, Story } from '@storybook/addon-docs/blocks'; +import CodeSnippet from '../CodeSnippet/CodeSnippet'; +import Spinner from '../Spinner/Spinner'; +import LoginPageLayout from './LoginPageLayout'; + + + + +export const Template = (args) => {args.children}; + +### LoginPageLayout + +This is a layout component that is used to display a page with a title and children. +The LoginPageLayout recommended usages are in the login flow like registration, sign up and error pages. + +### Props + + + +### Default + + + + {Template.bind({})} + + + +### Login page + + + + ), + }} + > + {Template.bind({})} + + + +### Error page + + + An error occurred. Try signing in again. + }, + ]} + /> + ), + }} + > + {Template.bind({})} + + + +### Registration page + + + +

Fill in the form below to create an account

+
+ + + + +
+ + ), + logo: { + src: "https://anbox-cloud.io/static/logo.svg", + title: "Anbox Cloud", + url: "/", + }, + }} + > + {Template.bind({})} +
+
+ diff --git a/src/components/LoginPageLayout/LoginPageLayout.tsx b/src/components/LoginPageLayout/LoginPageLayout.tsx new file mode 100644 index 000000000..74c18bdf2 --- /dev/null +++ b/src/components/LoginPageLayout/LoginPageLayout.tsx @@ -0,0 +1,48 @@ +import React, { FC, ReactNode, useEffect, useLayoutEffect } from "react"; +import Card from "components/Card"; +import Col from "components/Col"; +import Navigation from "components/Navigation"; +import Row from "components/Row"; +import { Theme } from "enums"; +import "./LoginPageLayout.scss"; + +const defaultLogo = { + src: "https://assets.ubuntu.com/v1/82818827-CoF_white.svg", + title: "Canonical", + url: "/", +}; + +export type Props = { + title: string; + children?: ReactNode; + logo?: { src: string; title: string; url: string }; +}; + +const LoginPageLayout: FC = ({ + children, + title, + logo = defaultLogo, +}) => { + useEffect(() => { + document.title = title; + }, [title]); + useLayoutEffect(() => { + document.querySelector("body")?.classList.add("is-paper"); + }); + + return ( + + + + +
+

{title}

+
{children}
+
+
+ +
+ ); +}; + +export default LoginPageLayout; diff --git a/src/components/LoginPageLayout/index.ts b/src/components/LoginPageLayout/index.ts new file mode 100644 index 000000000..8f04fe537 --- /dev/null +++ b/src/components/LoginPageLayout/index.ts @@ -0,0 +1,2 @@ +export { default } from "./LoginPageLayout"; +export type { Props as LoginPageLayoutProps } from "./LoginPageLayout"; diff --git a/src/index.ts b/src/index.ts index e4a003007..f2ef9e83e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,7 @@ export { failure, queue, } from "./components/NotificationProvider"; +export { default as LoginPageLayout } from "./components/LoginPageLayout"; export { default as Pagination } from "./components/Pagination"; export { default as PasswordToggle } from "./components/PasswordToggle"; export { default as RadioInput } from "./components/RadioInput"; @@ -120,6 +121,7 @@ export type { QueuedNotification, NotificationHelper, } from "./components/NotificationProvider"; +export type { LoginPageLayoutProps } from "./components/LoginPageLayout"; export type { PaginationProps } from "./components/Pagination"; export type { RadioInputProps } from "./components/RadioInput"; export type { RowProps } from "./components/Row";