Browse Source

appearence, motion, filters, aria, validation

master
ChiefRed 3 years ago
parent
commit
e0b683fd7f
17 changed files with 10925 additions and 1707 deletions
  1. +2
    -0
      package.json
  2. +19
    -23
      src/App.jsx
  3. +34
    -12
      src/Popup.jsx
  4. +10487
    -1605
      src/assets/styles/.index.css
  5. +3
    -1
      src/components/FormikControls/FormikControlErrorMessage.jsx
  6. +1
    -1
      src/components/FormikControls/FormikControlTypes/FormikControlCheckbox.jsx
  7. +12
    -3
      src/components/FormikControls/FormikControlTypes/FormikControlPassword.jsx
  8. +12
    -3
      src/components/FormikControls/FormikControlTypes/FormikControlString.jsx
  9. +46
    -0
      src/components/FormikControls/FormikControlTypes/FormikControlUserConsent.jsx
  10. +6
    -4
      src/components/FormikControls/index.js
  11. +10
    -7
      src/components/controls/ButtonPrimary.jsx
  12. +8
    -7
      src/components/controls/ButtonSecondary.jsx
  13. +2
    -2
      src/components/controls/Link.jsx
  14. +58
    -31
      src/components/forms/FormLogin.jsx
  15. +116
    -0
      src/components/forms/FormRegistration.jsx
  16. +102
    -8
      tailwind.js
  17. +7
    -0
      yarn.lock

+ 2
- 0
package.json View File

@@ -9,6 +9,7 @@
"@testing-library/user-event": "^7.1.2",
"autoprefixer": "9.8.6",
"postcss-cli": "^8.0.0",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.3"
@@ -41,6 +42,7 @@
"formik": "^2.1.7",
"framer-motion": "^2.7.7",
"tailwindcss": "^1.8.10",
"tailwindcss-filters": "^3.0.0",
"yup": "^0.29.3"
}
}

+ 19
- 23
src/App.jsx View File

@@ -3,43 +3,39 @@ import React, { useState } from 'react'
import ButtonPrimary from './components/controls/ButtonPrimary'
import Popup from './Popup';

import { FormLogin, FormLoginTitle } from './components/forms/FormLogin'
import { FormLogin } from './components/forms/FormLogin'
import { FormRegistration } from './components/forms/FormRegistration';


const App = () => {
const [popup, setPopup] = useState('')
const [popupTitle, setPopupTitle] = useState('')
const [popupContent, setPopupContent] = useState(<></>)
const [popupOpened, setPopupOpened] = useState(false)

const openPopup = (popupCode) => {
setPopup(popupCode)
const doOpenLoginPopup = () => {
setPopupContent(<FormLogin setPopupTitle={setPopupTitle} setPopupContent={setPopupContent} setPopupOpened={setPopupOpened} />)
setPopupOpened(true)
}

const closePopup = () => {
setPopupOpened(false)
}

let popupForm = null
let popupTitle = null

switch (popup) {
case 'login':
popupTitle = FormLoginTitle
popupForm = <FormLogin closePopup={closePopup} />
break
default:
popupTitle = null
popupForm = null
const doOpenRegistrationPopup = () => {
setPopupContent(<FormRegistration setPopupTitle={setPopupTitle} setPopupContent={setPopupContent} setPopupOpened={setPopupOpened} />)
setPopupOpened(true)
}

return (
<>
<div className="w-full h-full min-h-screen bg-blue-900">
<div className="max-w-lg mx-auto py-8">
<ButtonPrimary text="Login" action={() => openPopup('login')} />
<div className="w-full h-full min-h-screen bg-white text-gray-900 text-lg flex items-center">
<div className="max-w-lg w-full mx-auto py-8">
<div className="my-4">
<ButtonPrimary text="Login" action={doOpenLoginPopup} />
</div>
<div className="my-4">
<ButtonPrimary text="Registration" action={doOpenRegistrationPopup} />
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis voluptates necessitatibus impedit laudantium, ea quam voluptatibus unde nulla voluptas neque suscipit temporibus ipsam ducimus eum inventore libero, ullam soluta minima adipisci omnis! Deleniti alias perspiciatis et? Accusamus aliquam eveniet voluptas vitae tenetur quas quae maxime necessitatibus mollitia molestias, commodi sunt quibusdam, cum, vero qui exercitationem iste beatae eaque dicta odit deleniti dolorem! Eius itaque quasi quibusdam tempora fugit laboriosam magni quod vel voluptas, officiis culpa numquam, molestias tempore. Sapiente exercitationem doloremque velit dolores excepturi asperiores, cumque minus earum enim voluptatibus quod veritatis non tempora nemo quo officiis expedita eveniet ratione atque! Illo ab accusamus vero, quas quisquam soluta. Voluptatum repudiandae asperiores laboriosam blanditiis dolorum quo, minus porro consequuntur eius nihil illum quaerat quod, laudantium omnis temporibus inventore voluptate, explicabo libero numquam beatae saepe? Repudiandae perferendis nostrum sit nam ad eaque expedita doloribus? Deserunt perspiciatis quo nulla dolor voluptatum temporibus, beatae iusto veritatis laboriosam reiciendis cupiditate ab quisquam. Distinctio neque, voluptate enim, aliquam dignissimos inventore perspiciatis tempore, quae officia quis minima necessitatibus at repellendus. Animi corrupti at modi quas et ipsam asperiores a ducimus consequuntur necessitatibus! Tempore, quisquam? Magnam harum ducimus cupiditate aspernatur, sit veritatis ipsa ratione maxime similique fuga corporis consequuntur obcaecati quas provident ut! Dignissimos labore qui amet in, accusantium minus suscipit numquam saepe nulla hic vero molestias mollitia autem, magni rem illo fugit doloremque est consectetur? Iure laborum nesciunt possimus quod animi temporibus perspiciatis modi aspernatur alias, maxime, sint dolores. Ab quaerat beatae dolorem itaque ex, similique dolore consectetur voluptatibus tenetur maiores eaque tempore quos ullam facilis illo nisi ipsum veniam maxime pariatur sint iste? Modi voluptas molestias inventore omnis repellendus? Veniam alias rerum voluptatum aut possimus labore, iste neque recusandae eveniet aspernatur dolor mollitia accusantium repudiandae molestias magni odit illum dolorem iure nesciunt cumque commodi voluptatibus sed nobis! Labore sint optio voluptatum, harum minima ad cum dolorem inventore sed qui eligendi asperiores nihil, quisquam veniam unde quaerat eveniet ipsam reprehenderit. Molestias sequi sapiente, aperiam iusto nostrum obcaecati accusamus tenetur eum excepturi cupiditate voluptatem dolor consequuntur, modi nesciunt quibusdam nam quae, illo sed animi debitis praesentium deserunt! Obcaecati, repellendus odit. Commodi, omnis cupiditate qui atque debitis repellendus eius ipsam deserunt cum pariatur, ut illum nisi aspernatur exercitationem odit consectetur aliquam nam dignissimos minus non. Nam possimus totam doloremque ipsam architecto enim corrupti officia iste debitis ab nemo, exercitationem facere laborum optio magni earum, temporibus, impedit ipsa perferendis! Ex!</p>
</div>
</div>
<Popup opened={popupOpened} title={popupTitle} close={closePopup}>{popupForm}</Popup>
<Popup opened={popupOpened} title={popupTitle} close={() => setPopupOpened(false)}>{popupContent}</Popup>
</>
)
}

+ 34
- 12
src/Popup.jsx View File

@@ -1,11 +1,28 @@
import React from 'react';
import React from 'react'
import PropTypes from 'prop-types'
import { motion, AnimatePresence } from "framer-motion"

export function Popup({ opened, title, close, children }) {
export const Popup = (props) => {
const { opened, title, close, children } = props

const popupMotionVariants = {
hidden: { opacity: 0, scale: .9 },
visible: { opacity: 1, scale: 1 },
hidden: {
opacity: 0,
scaleY: 0,
transition: {
type: "linear",
duration: .3
}
},
visible: {
opacity: 1,
scaleY: 1,
transition: {
type: "spring",
damping: 50,
stiffness: 50000,
}
},
}

//document.body.style.overflow='hidden';
@@ -14,7 +31,7 @@ export function Popup({ opened, title, close, children }) {
<AnimatePresence>
{opened &&
<div className="modal z-50 fixed w-full min-h-screen top-0 left-0 flex items-center justify-center">
<div className="modal-overlay absolute top-0 left-0 w-full h-full bg-gray-100 opacity-75"></div>
<div className="modal-overlay absolute top-0 left-0 w-full h-full bg-primary-900 opacity-50 backdrop-blur"></div>
<div className="modal-wrapper relative w-full">
<div className="max-w-full max-h-screen sm:max-w-lg mx-auto">
<motion.div
@@ -22,16 +39,13 @@ export function Popup({ opened, title, close, children }) {
initial="hidden"
animate="visible"
exit="hidden"
transition={{ duration: .1 }}
>
<div className="ma-0 bg-white shadow-lg border-gray-500 border-t-2 border-b-2 sm:border-2 sm:mx-4 sm:rounded-lg transition-opacity duration-300" onClick={e => e.stopPropagation()}>
<div className="px-3 h-12 border-b border-gray-400 font-semibold relative flex items-center">
<div tabIndex="0" aria-label={title} aria-modal className="ma-0 bg-gray-200 shadow-lg border-white border-t-2 border-b-2 sm:border-2 sm:mx-4 sm:rounded-lg transition-opacity duration-300" onClick={e => e.stopPropagation()}>
<div className="px-3 h-12 bg-primary-800 text-white border-b sm:rounded-t-lg border-white font-semibold relative flex items-center">
<div className="w-full text-xl">{title}</div>
<div className="absolute top-0 right-0 w-12 h-12 pb-1 text-3xl leading-none cursor-pointer flex items-center justify-center" onClick={close}>&times;</div>
</div>
<div className="">
{children}
<button type="button" aria-label="Close modal" className="absolute top-0 right-0 w-12 h-12 pb-1 text-3xl leading-none cursor-pointer flex items-center justify-center" onClick={close}>&times;</button>
</div>
{children}
</div>
</motion.div>
</div>
@@ -44,3 +58,11 @@ export function Popup({ opened, title, close, children }) {
}

export default Popup;


Popup.propTypes = {
opened: PropTypes.bool,
title: PropTypes.string,
close: PropTypes.func,
children: PropTypes.element,
}

+ 10487
- 1605
src/assets/styles/.index.css
File diff suppressed because it is too large
View File


+ 3
- 1
src/components/FormikControls/FormikControlErrorMessage.jsx View File

@@ -1,7 +1,9 @@
import React from 'react'

function FormikControlErrorMessage(props) {
return <div className='error text-sm text-secondary-dark mt-1'>{props.children}</div>
const {name, label, className, children, ...rest} = props
const classNames = ['error text-right text-sm text-red-700 mt-1 mr-1', className].join(' ');
return <div className={classNames} {...rest}><span className="sr-only">{label} field validation error message: </span>{children}</div>
}

export default FormikControlErrorMessage

+ 1
- 1
src/components/FormikControls/FormikControlTypes/FormikControlCheckbox.jsx View File

@@ -12,7 +12,7 @@ function FormikControlCheckbox(props) {
const htmlId = newId()
return <>
<label htmlFor={htmlId} className="inline-flex items-center py-1">
<input type="checkbox" id={htmlId} name={name} {...rest} className="form-checkbox text-primary-dark" {...field} checked={field.value} />
<input type="checkbox" id={htmlId} name={name} {...rest} className="form-checkbox text-primary-800" {...field} checked={field.value} />
<span className="ml-4 text-base sm:text-lg ">{label}</span>
</label>
</>

+ 12
- 3
src/components/FormikControls/FormikControlTypes/FormikControlPassword.jsx View File

@@ -9,10 +9,19 @@ function FormikControlPassword(props) {
return (
<div className="mt-4 mb-2">
<label htmlFor={htmlId} className="form-control block text-lg text-gray-800 py-1">
<span className="text-gray-700">{label}</span>
<Field type="password" id={htmlId} name={name} {...rest} className="form-input mt-1 block w-full text-center tracking-widest" />
<ErrorMessage component={FormikControlErrorMessage} name={name} />
<span className="text-gray-700 ml-1">{label}</span>
</label>
<Field
type="password"
label={label}
title={label}
id={htmlId}
name={name}
aria-describedby={name + 'Error'}
{...rest}
className="form-input mt-1 block w-full text-center tracking-widest"
/>
<ErrorMessage component={FormikControlErrorMessage} name={name} label={label} id={name + 'Error'} />
</div>
)
}

+ 12
- 3
src/components/FormikControls/FormikControlTypes/FormikControlString.jsx View File

@@ -9,10 +9,19 @@ function FormikControlString(props) {
return (
<div className="mt-4 mb-2">
<label htmlFor={htmlId} className="form-control block text-lg text-gray-800 py-1">
<span className="text-gray-700">{label}</span>
<Field type="text" id={htmlId} name={name} {...rest} className="form-input mt-1 block w-full text-center tracking-widest" />
<ErrorMessage component={FormikControlErrorMessage} name={name} />
<span className="text-gray-700 ml-1">{label}</span>
</label>
<Field
type="text"
label={label}
title={label}
id={htmlId}
name={name}
aria-describedby={name + 'Error'}
{...rest}
className="form-input mt-1 block w-full text-center tracking-widest"
/>
<ErrorMessage component={FormikControlErrorMessage} name={name} label={label} id={name + 'Error'} />
</div>
)
}

+ 46
- 0
src/components/FormikControls/FormikControlTypes/FormikControlUserConsent.jsx View File

@@ -0,0 +1,46 @@
import React from 'react'
import { Field, ErrorMessage } from 'formik'
import FormikControlErrorMessage from '../FormikControlErrorMessage'
import newId from '../../../utils/newId';

function FormikControlUserConsent(props) {
const { name, label_template, label_action, ...rest } = props
const label = label_template.replace(/#+/g, '')
const Link = ({ label_template, label_action }) => {
const rx = /^([^#]*)#([^#]+)#([^#]*)$/
if (!label_template || !label_template.match(rx)) return false
const parts = label_template.split(rx);
return <>
{parts[1]}<button type="button" tabIndex="0" onClick={label_action} className="text-primary-800 hover:underline flex-grow rounded-md outline-none focus:outline-none focus:shadow-outline">{parts[2]}</button>{parts[3]}
</>
}
if (!Link({ label_template, label_action })) return false
const htmlId = newId()
return (
<div className="form-control mt-6 mb-4">
<Field name={name}>
{({ field }) => {
return <>
<label htmlFor={htmlId} className="inline-flex items-center py-1">
<input
type="checkbox"
id={htmlId}
title={label}
name={name}
{...rest}
className="form-checkbox text-primary-800"
{...field}
checked={field.value}
aria-describedby={name + 'Error'}
/>
<span className="ml-8 text-base sm:text-lg "><Link label_template={label_template} label_action={label_action} /></span>
</label>
</>
}}
</Field>
<ErrorMessage component={FormikControlErrorMessage} name={name} label={label} id={name + 'Error'} />
</div>
)
}

export default FormikControlUserConsent

+ 6
- 4
src/components/FormikControls/index.js View File

@@ -1,6 +1,8 @@
import React from 'react'
import FormikControlString from './FormikControlTypes/FormikControlString'
import FormikControlPassword from './FormikControlTypes/FormikControlPassword'
import FormikControlUserConsent from './FormikControlTypes/FormikControlUserConsent'
import FormikControlCheckbox from './FormikControlTypes/FormikControlCheckbox'


export function FormikControl(props) {
@@ -18,12 +20,12 @@ export function FormikControl(props) {
// return <FormikInputRadioGroup {...rest} />
// case 'checkbox':
// return <FormikInputCheckbox {...rest} />
// case 'checkboxs':
// return <FormikInputCheckboxGroup {...rest} />
// case 'userconsent':
// return <FormikInputUserConsent {...rest} />
// case 'phone':
// return <FormikInputPhone {...rest} />
case 'userconsent':
return <FormikControlUserConsent {...rest} />
case 'checkbox':
return <FormikControlCheckbox {...rest} />
default:
return null
}

+ 10
- 7
src/components/controls/ButtonPrimary.jsx View File

@@ -1,6 +1,7 @@
import React from 'react'

function PrimaryButton({type, text, action, disabled}) {
function PrimaryButton(props) {
const {type, text, action, disabled} = props
return <>
<button
type={type||'button'}
@@ -12,19 +13,19 @@ function PrimaryButton({type, text, action, disabled}) {
p-3
border-0
rounded-md
border-primary-dark
bg-primary-dark
border-primary-800
bg-primary-800
text-white
cursor-pointer
shadow-md
hover:bg-primary-light
focus:bg-primary-light
hover:bg-primary-500
focus:bg-primary-500
focus:outline-none
active:shadow-inner
active:bg-primary-dark
active:bg-primary-800
active:transform
active:translate-y-px
disabled:bg-primary-dark
disabled:bg-primary-800
disabled:opacity-50
disabled:shadow-md
disabled:translate-y-0
@@ -32,9 +33,11 @@ function PrimaryButton({type, text, action, disabled}) {
"
onClick={action}
disabled={disabled}
aria-disabled={disabled}
>
<div className="sm:text-lg flex-grow text-center px-6">{text||'Primary Button'}</div>
</button>
{disabled && <div tabIndex="0" className="sr-only">Disabled button: {text||'Primary Button'}. Please fill all necessary fields.</div>}
</>
}
export default PrimaryButton

+ 8
- 7
src/components/controls/ButtonSecondary.jsx View File

@@ -1,6 +1,7 @@
import React from 'react'

function Buttonprimary({type, text, action, disabled}) {
function ButtonSecondary(props) {
const {type, text, action, disabled} = props
return <>
<button
type={type||'button'}
@@ -12,17 +13,17 @@ function Buttonprimary({type, text, action, disabled}) {
p-3
border-2
rounded-md
border-primary-dark
border-primary-800
bg-white
text-primary-dark
text-primary-800
cursor-pointer
shadow-md
hover:bg-primary-light
hover:bg-primary-500
hover:text-white
focus:bg-primary-light
focus:bg-primary-500
focus:outline-none
active:shadow-inner
active:bg-primary-light
active:bg-primary-500
active:transform
active:translate-y-px
disabled:bg-white
@@ -38,4 +39,4 @@ function Buttonprimary({type, text, action, disabled}) {
</button>
</>
}
export default Buttonprimary
export default ButtonSecondary

+ 2
- 2
src/components/controls/Link.jsx View File

@@ -2,9 +2,9 @@ import React from 'react'

function Link(props) {
const { action, children, className, ...rest } = props
const classNames = ['text-primary-dark cursor-pointer hover:underline', className].join(' ');
const classNames = ['text-primary-700 cursor-pointer hover:underline rounded-md outline-none focus:outline-none focus:shadow-outline', className].join(' ');
return (
<span onClick={action} className={classNames} {...rest}>{children}</span>
<button type="button" tabIndex="0" onClick={action} className={classNames} {...rest}>{children}</button>
)
}


+ 58
- 31
src/components/forms/FormLogin.jsx View File

@@ -1,13 +1,19 @@
import React from 'react'
import React, { useEffect } from 'react'
import PropTypes from 'prop-types'
import { Formik, Form } from 'formik'
import * as Yup from 'yup'
import FormikControl from '../FormikControls'
import ButtonPrimary from '../controls/ButtonPrimary'
import ButtonSecondary from '../controls/ButtonSecondary'
import Link from '../controls/Link'
import { FormRegistration } from './FormRegistration'

export const FormLoginTitle = 'Authentication'
export const FormLogin = (props) => {
const { setPopupTitle, setPopupContent, setPopupOpened } = props

export const FormLogin = () => {
useEffect(() => {
if (setPopupTitle) { setPopupTitle('Enter into restricted area') }
})

const initialValues = {
login: '',
@@ -16,7 +22,7 @@ export const FormLogin = () => {
}

const validationSchema = Yup.object({
login: Yup.string()
email: Yup.string()
.required('Required'),
password: Yup.string()
.required('Required'),
@@ -27,7 +33,19 @@ export const FormLogin = () => {
}

const goRegistration = () => {
console.log('goRegistration')
setPopupOpened(false)
setTimeout(() => {
setPopupContent(<FormRegistration setPopupTitle={setPopupTitle} setPopupContent={setPopupContent} setPopupOpened={setPopupOpened} />)
setPopupOpened(true)
}, 200);
}

const goRestorePassword = () => {
setPopupOpened(false)
setTimeout(() => {
setPopupContent(<FormRegistration setPopupTitle={setPopupTitle} setPopupContent={setPopupContent} setPopupOpened={setPopupOpened} />)
setPopupOpened(true)
}, 200);
}

return (
@@ -38,39 +56,48 @@ export const FormLogin = () => {
>
{formik => {
return (
<Form>
<div className="overflow-y-auto max-screen--mt-12 p-3">
<FormikControl
control='string'
name='login'
label='Login'
placeholder='Enter Login'
/>
<FormikControl
control='password'
name='password'
label='Password'
placeholder='Enter Password'
/>
<div className="flex flex-col xs:flex-row justify-between items-center xs:items-start">
<div>
<div className="overflow-y-auto max-h-screen-75">
<Form>
<div className="p-3">
<FormikControl
control='checkbox'
name='remember_me'
label='Remember Me'
control='string'
name='email'
label='E-mail'
placeholder='Enter e-mail'
/>
<FormikControl
control='password'
name='password'
label='Password'
placeholder='Enter password'
/>
<div className="flex xs:flex-row justify-between items-center xs:items-center">
<div>
<FormikControl
control='checkbox'
name='remember_me'
label='Remember me'
/>
</div>
<Link action={goRestorePassword} className="block px-2 mt-6 mb-4 leading-8 text-lg">Forgot password?</Link>
</div>
</div>
</div>
<div className="p-3 border-t border-gray-400">
<ButtonPrimary type="submit" text="LogIn" disabled={!formik.isValid || !formik.dirty} />
<div className="my-3">
<ButtonSecondary type="button" text="SignIn" action={goRegistration} />
<div className="px-2 pt-4 pb-1 mb-0 bg-primary-200 border-t sm:rounded-b-lg">
<ButtonPrimary type="submit" text="Enter" disabled={!formik.isValid || !formik.dirty} />
<div className="my-3">
<ButtonSecondary type="button" text="Have no account? - Create" action={goRegistration} />
</div>
</div>
</div>
</Form>
</Form>
</div>
)
}}
</Formik>
)
}

FormLogin.propTypes = {
setPopupTitle: PropTypes.func,
setPopupContent: PropTypes.func,
setPopupOpened: PropTypes.func,
}

+ 116
- 0
src/components/forms/FormRegistration.jsx View File

@@ -0,0 +1,116 @@
import React, { useEffect } from 'react'
import PropTypes from 'prop-types'
import { Formik, Form } from 'formik'
import * as Yup from 'yup'
import FormikControl from '../FormikControls'
import ButtonPrimary from '../controls/ButtonPrimary'
import ButtonSecondary from '../controls/ButtonSecondary'
import { FormLogin } from './FormLogin'

export const FormRegistration = (props) => {
const { setPopupTitle, setPopupContent, setPopupOpened } = props

useEffect(() => {
if (setPopupTitle) { setPopupTitle('New user registration') }
})

const initialValues = {
email: '',
password: '',
password_confirm: '',
userconsent: false,
}

const validationSchema = Yup.object({
email: Yup.string()
.required('Required')
.email('Must be a valid email address'),
password: Yup.string()
.required('Required')
.min(8, 'Minimum 8 symbols'),
password_confirm: Yup.string()
.required('Required')
.oneOf([Yup.ref('password'), null], 'Not matching with password'),
userconsent: Yup.boolean()
.oneOf([true], 'Required'),
})

const onSubmit = async values => {
console.log('Form data', values)
}

const goLogin = () => {
setPopupOpened(false)
setTimeout(() => {
setPopupContent(<FormLogin setPopupTitle={setPopupTitle} setPopupContent={setPopupContent} setPopupOpened={setPopupOpened} />)
setPopupOpened(true)
}, 200);
}

return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{formik => {
return (
<div className="overflow-y-auto max-h-screen-75">
<Form>
<div className="p-3">
<FormikControl
control='string'
name='email'
label='E-mail'
placeholder='Enter e-mail'
required
aria-required="true"
aria-invalid={!!formik.errors.email}
/>
<FormikControl
control='password'
name='password'
label='Password'
placeholder='Enter password'
required
aria-required="true"
aria-invalid={!!formik.errors.password}
/>
<FormikControl
control='password'
name='password_confirm'
label='Conform password'
placeholder='Enter same password'
required
aria-required="true"
aria-invalid={!!formik.errors.password_confirm}
/>
<FormikControl
control='userconsent'
name='userconsent'
label_template='Accept #Service Policy#'
label_action={() => { alert('Policy text here') }}
required
aria-required="true"
aria-invalid={!!formik.errors.userconsent}
/>
</div>
<div className="px-2 pt-4 pb-1 mb-0 bg-primary-200 border-t rounded-b-lg">
<ButtonPrimary type="submit" text="Register" disabled={!formik.isValid || !formik.dirty} />
<div className="my-3">
<ButtonSecondary type="button" text="Have account? - Sign In" action={goLogin} />
</div>
</div>
</Form>
</div>
)
}}
</Formik>
)
}

FormRegistration.propTypes = {
setPopupTitle: PropTypes.func,
setPopupContent: PropTypes.func,
setPopupOpened: PropTypes.func,
}

+ 102
- 8
tailwind.js View File

@@ -22,14 +22,27 @@ module.exports = {
current: 'currentColor',

primary: {
semitransparent: "#EF303D1F",
light: "#EF303D",
dark: "#94070C",
100: "#e2e2f4",
200: "#c4c5e8",
300: "#a7a9dd",
400: "#898cd1",
500: "#6c6fc6",
600: "#4f52ba",
700: "#3f42a2",
800: "#333684",
900: "#282b67",
},

secondary: {
light: "#FFE9C6",
dark: "#EBB35C",
100: "#eceaac",
200: "#e5e28b",
300: "#ddd969",
400: "#d5d148",
500: "#c8c22d",
600: "#a6a226",
700: "#85821e",
800: "#646117",
900: "#43410f",
},

black: '#000',
@@ -226,7 +239,7 @@ module.exports = {
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
outline: '0 0 0 3px rgba(148, 7, 12, 0.5)',
outline: '0 0 0 3px #33368480',
none: 'none',
},
container: {},
@@ -349,6 +362,9 @@ module.exports = {
maxHeight: {
full: '100%',
screen: '100vh',
'screen-25': '25vh',
'screen-50': '50vh',
'screen-75': '75vh',
},
maxWidth: (theme, { breakpoints }) => ({
none: 'none',
@@ -680,6 +696,79 @@ module.exports = {
},
},
},
customForms: theme => ({
default: {
input: {
borderRadius: theme('borderRadius.lg'),
borderWidth: theme('borderWidth.2'),
backgroundColor: theme('colors.white'),
'&:focus': {
backgroundColor: theme('colors.secondary.100'),
boxShadow: theme('boxShadow.outline'),
outline: 'none',
borderColor: theme('colors.transparent'),
},
'&:active': {
backgroundColor: theme('colors.secondary.100'),
}
},
textarea: {
borderRadius: theme('borderRadius.lg'),
borderWidth: theme('borderWidth.2'),
backgroundColor: theme('colors.white'),
'&:focus': {
backgroundColor: theme('colors.secondary.100'),
boxShadow: theme('boxShadow.outline'),
outline: 'none',
borderColor: theme('colors.transparent'),
},
'&:active': {
backgroundColor: theme('colors.secondary.100'),
}
},
select: {
borderWidth: theme('borderWidth.2'),
borderRadius: theme('borderRadius.lg'),
'&:focus': {
boxShadow: theme('boxShadow.outline'),
backgroundColor: theme('colors.secondary.100'),
outline: 'none',
borderColor: theme('colors.transparent'),
},
'&:active': {
backgroundColor: theme('colors.secondary.100'),
}
},
checkbox: {
borderWidth: theme('borderWidth.2'),
width: theme('spacing.6'),
height: theme('spacing.6'),
'&:focus': {
boxShadow: theme('boxShadow.outline'),
outline: 'none',
borderColor: theme('colors.transparent'),
},
},
radio: {
iconColor: theme('colors.primary.800'),
'&:focus': {
boxShadow: theme('boxShadow.outline'),
outline: 'none',
borderColor: theme('colors.transparent'),
},
},
},
}),
filter: { // defaults to {}
'none': 'none',
'grayscale': 'grayscale(1)',
'invert': 'invert(1)',
'sepia': 'sepia(1)',
},
backdropFilter: { // defaults to {}
'none': 'none',
'blur': 'blur(20px)',
},
},
variants: {
accessibility: ['responsive', 'focus'],
@@ -705,7 +794,7 @@ module.exports = {
boxShadow: ['responsive', 'hover', 'focus', 'active', 'disabled'],
boxSizing: ['responsive'],
container: ['responsive'],
cursor: ['responsive'],
cursor: ['responsive', 'disabled'],
display: ['responsive'],
divideColor: ['responsive'],
divideOpacity: ['responsive'],
@@ -792,7 +881,12 @@ module.exports = {
transitionDuration: ['responsive'],
transitionDelay: ['responsive'],
animation: ['responsive'],
filter: ['responsive'], // defaults to ['responsive']
backdropFilter: ['responsive'], // defaults to ['responsive']
},
corePlugins: {},
plugins: [],
plugins: [
require('@tailwindcss/custom-forms'),
require('tailwindcss-filters'),
],
}

+ 7
- 0
yarn.lock View File

@@ -10447,6 +10447,13 @@ table@^5.2.3:
slice-ansi "^2.1.0"
string-width "^3.0.0"

tailwindcss-filters@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/tailwindcss-filters/-/tailwindcss-filters-3.0.0.tgz#d5d40ca018a54b1aa2bdc57aeb6677529c24c8d8"
integrity sha512-xhortqs8fSp9id17EnneYhmruA5DfU6K0zvN6/mgDlEXKaHthjXlR74Ta+4lrX5Lp7tp6YigB09WO0TOWn7VEQ==
dependencies:
lodash "^4.17.15"

tailwindcss@^1.8.10:
version "1.8.10"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-1.8.10.tgz#945ef151c401c04a1c95e6a6bc747387a8d1b9dc"

Loading…
Cancel
Save