mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-22 09:13:37 +01:00
Form components. New login page.
This commit is contained in:
parent
9d09d89aef
commit
a09867f28c
1
assets/logo.svg
Normal file
1
assets/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 428 389.11"><defs><style>.cls-1{fill:#fff;stroke:#000;stroke-miterlimit:10;stroke-width:20px;}</style></defs><title>Asset 2</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_3" data-name="Layer 3"><circle class="cls-1" cx="214.15" cy="181" r="171"/><path d="M0,175.11c0,118.19,95.81,214,214,214s214-95.81,214-214a215.65,215.65,0,0,0-3-36H3A215.65,215.65,0,0,0,0,175.11Z"/><rect x="0.29" y="134.11" width="427.71" height="60" rx="15"/></g></g></svg>
|
After Width: | Height: | Size: 507 B |
20
components/FormLayout.js
Normal file
20
components/FormLayout.js
Normal file
@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ErrorMessage } from 'formik';
|
||||
import styles from './FormLayout.module.css';
|
||||
|
||||
export default function FormLayout({ className, children }) {
|
||||
return <div className={classNames(styles.form, className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export const FormButtons = ({ className, children }) => (
|
||||
<div className={classNames(styles.buttons, className)}>{children}</div>
|
||||
);
|
||||
|
||||
export const FormError = ({ name }) => (
|
||||
<ErrorMessage name={name}>{msg => <div className={styles.error}>{msg}</div>}</ErrorMessage>
|
||||
);
|
||||
|
||||
export const FormRow = ({ children }) => <div className={styles.row}>{children}</div>;
|
||||
|
||||
export const FormMessage = ({ children }) => <div className={styles.message}>{children}</div>;
|
48
components/FormLayout.module.css
Normal file
48
components/FormLayout.module.css
Normal file
@ -0,0 +1,48 @@
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.form label {
|
||||
display: inline-block;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--gray50);
|
||||
background: var(--color-error);
|
||||
font-size: var(--font-size-small);
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
bottom: 0;
|
||||
margin-left: 10px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.message {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
color: var(--gray50);
|
||||
background: var(--gray800);
|
||||
}
|
@ -3,6 +3,8 @@ import { useSelector } from 'react-redux';
|
||||
import classNames from 'classnames';
|
||||
import Link from 'components/Link';
|
||||
import UserButton from './UserButton';
|
||||
import Icon from './Icon';
|
||||
import Logo from 'assets/logo.svg';
|
||||
import styles from './Header.module.css';
|
||||
|
||||
export default function Header() {
|
||||
@ -12,7 +14,10 @@ export default function Header() {
|
||||
<header className={classNames(styles.header, 'container')}>
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<div className={styles.title}>{user ? <Link href="/">umami</Link> : 'umami'}</div>
|
||||
<div className={styles.title}>
|
||||
<Icon icon={<Logo />} size="L" className={styles.logo} />
|
||||
{user ? <Link href="/">umami</Link> : 'umami'}
|
||||
</div>
|
||||
</div>
|
||||
{user && (
|
||||
<div className="col">
|
||||
|
@ -23,3 +23,7 @@
|
||||
font-weight: 600;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ export default function Icon({ icon, className, size = 'M' }) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.icon, className, {
|
||||
[styles.xl]: size === 'XL',
|
||||
[styles.large]: size === 'L',
|
||||
[styles.medium]: size === 'M',
|
||||
[styles.small]: size === 'S',
|
||||
|
@ -9,6 +9,11 @@
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.xl > svg {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.large > svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
@ -1,9 +1,18 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Head from 'next/head';
|
||||
import Header from 'components/Header';
|
||||
import Footer from 'components/Footer';
|
||||
import styles from './Layout.module.css';
|
||||
|
||||
export default function Layout({ title, children }) {
|
||||
export default function Layout({
|
||||
title,
|
||||
children,
|
||||
header = true,
|
||||
footer = true,
|
||||
center = false,
|
||||
middle = false,
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@ -14,9 +23,16 @@ export default function Layout({ title, children }) {
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</Head>
|
||||
<Header />
|
||||
<main className="container">{children}</main>
|
||||
<Footer />
|
||||
{header && <Header />}
|
||||
<main
|
||||
className={classNames(styles.layout, 'container', {
|
||||
[styles.center]: center,
|
||||
[styles.middle]: middle,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</main>
|
||||
{footer && <Footer />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
12
components/Layout.module.css
Normal file
12
components/Layout.module.css
Normal file
@ -0,0 +1,12 @@
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.middle {
|
||||
justify-content: center;
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Formik, Form, Field, ErrorMessage } from 'formik';
|
||||
import { Formik, Form, Field } from 'formik';
|
||||
import Router from 'next/router';
|
||||
import { post } from 'lib/web';
|
||||
import Button from './Button';
|
||||
import FormLayout, { FormButtons, FormError, FormMessage, FormRow } from './FormLayout';
|
||||
import styles from './Login.module.css';
|
||||
|
||||
const validate = ({ username, password }) => {
|
||||
@ -32,30 +33,35 @@ export default function Login() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{
|
||||
username: '',
|
||||
password: '',
|
||||
}}
|
||||
validate={validate}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form className={styles.form}>
|
||||
<h3>{message}</h3>
|
||||
<div>
|
||||
<label htmlFor="username">Username</label>
|
||||
<Field name="username" type="text" />
|
||||
<ErrorMessage name="username" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="password">Password</label>
|
||||
<Field name="password" type="password" />
|
||||
<ErrorMessage name="password" />
|
||||
</div>
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
<FormLayout>
|
||||
<Formik
|
||||
initialValues={{
|
||||
username: '',
|
||||
password: '',
|
||||
}}
|
||||
validate={validate}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form>
|
||||
<h1 className={styles.title}>umami</h1>
|
||||
<FormRow>
|
||||
<label htmlFor="username">Username</label>
|
||||
<Field name="username" type="text" />
|
||||
<FormError name="username" />
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
<label htmlFor="password">Password</label>
|
||||
<Field name="password" type="password" />
|
||||
<FormError name="password" />
|
||||
</FormRow>
|
||||
<FormButtons>
|
||||
<Button type="submit">Login</Button>
|
||||
</FormButtons>
|
||||
<FormMessage>{message}</FormMessage>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</FormLayout>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
.form {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
.title {
|
||||
font-size: var(--font-size-xlarge);
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import React from 'react';
|
||||
import Layout from 'components/Layout';
|
||||
import Login from 'components/Login';
|
||||
import Icon from 'components/Icon';
|
||||
import Logo from 'assets/logo.svg';
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<Layout title="login">
|
||||
<Layout title="login" header={false} footer={false} center middle>
|
||||
<Icon icon={<Logo />} size="XL" />
|
||||
<Login />
|
||||
</Layout>
|
||||
);
|
||||
|
@ -19,7 +19,12 @@ body {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
h2 {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@ -42,16 +47,9 @@ a:visited {
|
||||
color: var(--primary400);
|
||||
}
|
||||
|
||||
form label {
|
||||
display: inline-block;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
padding: 4px 8px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 20px;
|
||||
font-size: var(--font-size-normal);
|
||||
line-height: 1.8;
|
||||
border: 1px solid var(--gray500);
|
||||
|
@ -7,7 +7,7 @@
|
||||
--gray400: #cacaca;
|
||||
--gray500: #b3b3b3;
|
||||
--gray600: #8e8e8e;
|
||||
--gray6700: #6e6e6e;
|
||||
--gray700: #6e6e6e;
|
||||
--gray800: #4b4b4b;
|
||||
--gray900: #2c2c2c;
|
||||
|
||||
@ -26,4 +26,6 @@
|
||||
--grid-size-medium: 768px;
|
||||
--grid-size-large: 992px;
|
||||
--grid-size-xlarge: 1140px;
|
||||
|
||||
--color-error: #e34850;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user