Start working on some defined styles, begin implementing password update in account
This commit is contained in:
parent
0789b814dd
commit
adcd2682ef
8 changed files with 226 additions and 91 deletions
|
@ -15,19 +15,23 @@ input[type=number] {
|
||||||
/**
|
/**
|
||||||
* Styling for other forms throughout the Panel.
|
* Styling for other forms throughout the Panel.
|
||||||
*/
|
*/
|
||||||
.input {
|
.input, .input-dark {
|
||||||
@apply .appearance-none .p-3 .rounded .border .border-neutral-200 .text-neutral-800 .w-full;
|
@apply .appearance-none .w-full;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
|
&:required, &:invalid {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
@apply .p-3 .rounded .border .border-neutral-200 .text-neutral-800;
|
||||||
transition: border 150ms linear;
|
transition: border 150ms linear;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
@apply .border-primary-400;
|
@apply .border-primary-400;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:required, &:invalid {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
@apply .text-red-600 .border-red-500;
|
@apply .text-red-600 .border-red-500;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +41,39 @@ input[type=number] {
|
||||||
@apply .bg-neutral-100 .border-neutral-200;
|
@apply .bg-neutral-100 .border-neutral-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input + .input-help {
|
||||||
|
@apply .text-xs .text-neutral-400 .pt-2;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
@apply .text-red-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-dark {
|
||||||
|
@apply .p-3 .bg-neutral-600 .border .border-neutral-500 .text-sm .rounded .text-neutral-200;
|
||||||
|
transition: border 150ms linear, box-shaodw 150ms ease-in;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
@apply .shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
& + .input-help {
|
||||||
|
@apply .text-xs .text-neutral-400 .mt-2
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
@apply .text-red-100 .border-red-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error + .input-help {
|
||||||
|
@apply .text-red-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
@apply .opacity-75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
@apply .block .text-xs .font-medium .uppercase .text-neutral-700 .mb-2;
|
@apply .block .text-xs .font-medium .uppercase .text-neutral-700 .mb-2;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +98,10 @@ select:not(.appearance-none) {
|
||||||
background-position-x: calc(100% - 0.75rem);
|
background-position-x: calc(100% - 0.75rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-dark-label {
|
||||||
|
@apply .uppercase .text-neutral-200;
|
||||||
|
}
|
||||||
|
|
||||||
.input-label {
|
.input-label {
|
||||||
@apply .block .uppercase .tracking-wide .text-neutral-800 .text-xs .font-bold;
|
@apply .block .uppercase .tracking-wide .text-neutral-800 .text-xs .font-bold;
|
||||||
|
|
||||||
|
@ -69,60 +110,60 @@ select:not(.appearance-none) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-help {
|
|
||||||
@apply .text-xs .text-neutral-400 .pt-2;
|
|
||||||
|
|
||||||
&.error {
|
|
||||||
@apply .text-red-600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a.btn {
|
a.btn {
|
||||||
@apply .no-underline;
|
@apply .no-underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
@apply .rounded .p-2;
|
@apply .rounded .p-2 .uppercase .tracking-wide .text-sm;
|
||||||
transition: all 150ms linear;
|
transition: all 150ms linear;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button Colors
|
* Button Colors
|
||||||
*/
|
*/
|
||||||
&.btn-primary {
|
&.btn-primary {
|
||||||
@apply .bg-primary-500 .border-primary-600 .border .text-white;
|
@apply .bg-primary-500 .border-primary-600 .border .text-primary-50;
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
@apply .bg-primary-600 .border-primary-800;
|
@apply .bg-primary-600 .border-primary-700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-green {
|
&.btn-green {
|
||||||
@apply .bg-green-500 .border-green-600 .border .text-white;
|
@apply .bg-green-500 .border-green-600 .border .text-green-50;
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
@apply .bg-green-600 .border-green-800;
|
@apply .bg-green-600 .border-green-700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-red {
|
&.btn-red {
|
||||||
&:not(.btn-secondary) {
|
&:not(.btn-secondary) {
|
||||||
@apply .bg-red-500 .border-red-600 .border .text-white;
|
@apply .bg-red-500 .border-red-600 .text-red-50;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
@apply .bg-red-600 .border-red-800;
|
@apply .bg-red-600 .border-red-700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-grey {
|
||||||
|
@apply .border .border-neutral-600 .bg-neutral-500 .text-neutral-50;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
@apply .bg-neutral-600 .border-neutral-700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-secondary {
|
&.btn-secondary {
|
||||||
@apply .border .border-neutral-200 .text-neutral-400;
|
@apply .border .border-neutral-600 .bg-transparent .text-neutral-200;
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
@apply .border-neutral-500 .text-neutral-700;
|
@apply .border-neutral-500 .text-neutral-100;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-red:hover:not(:disabled) {
|
&.btn-red:hover:not(:disabled) {
|
||||||
@apply .bg-red-600 .border-red-800 .text-white;
|
@apply .bg-red-500 .border-red-600 .text-red-50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,19 +171,19 @@ a.btn {
|
||||||
* Button Sizes
|
* Button Sizes
|
||||||
*/
|
*/
|
||||||
&.btn-jumbo {
|
&.btn-jumbo {
|
||||||
@apply .p-4 .w-full .uppercase .tracking-wide .text-sm;
|
@apply .p-4 .w-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-lg {
|
&.btn-lg {
|
||||||
@apply .p-4 .uppercase .tracking-wide .text-sm;
|
@apply .p-4 .text-sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-sm {
|
&.btn-sm {
|
||||||
@apply .px-6 .py-3 .uppercase .tracking-wide .text-sm;
|
@apply .p-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-xs {
|
&.btn-xs {
|
||||||
@apply .py-2 .px-2 .uppercase .text-xs;
|
@apply .p-2 .text-xs;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled, &.disabled {
|
&:disabled, &.disabled {
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
export default class AccountOverview extends React.PureComponent {
|
|
||||||
render () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import ContentBox from '@/components/elements/ContentBox';
|
||||||
|
import UpdatePasswordForm from '@/components/account/forms/UpdatePasswordForm';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (
|
||||||
|
<div className={'flex my-10'}>
|
||||||
|
<ContentBox className={'flex-1 mr-4'} title={'Update Password'}>
|
||||||
|
<UpdatePasswordForm/>
|
||||||
|
</ContentBox>
|
||||||
|
<div className={'flex-1 ml-4'}>
|
||||||
|
<ContentBox title={'Update Email Address'}>
|
||||||
|
</ContentBox>
|
||||||
|
<ContentBox title={'Update Identity'} className={'mt-8'}>
|
||||||
|
</ContentBox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,53 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
export default class DesignElements extends React.PureComponent {
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<div className={'my-10'}>
|
|
||||||
<div className={'flex'}>
|
|
||||||
<div className={'flex-1 mr-4'}>
|
|
||||||
<h2 className={'text-neutral-300 mb-2 px-4'}>A Special Announcement</h2>
|
|
||||||
<div className={'bg-neutral-700 p-4 rounded shadow-lg border-t-4 border-primary-400'}>
|
|
||||||
<p className={'text-neutral-200 text-sm'}>
|
|
||||||
Your demands have been received: Dark Mode will be default in Pterodactyl 0.8!
|
|
||||||
</p>
|
|
||||||
<p><Link to={'/'}>Back</Link></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={'ml-4 flex-1'}>
|
|
||||||
<h2 className={'text-neutral-300 mb-2 px-4'}>Form Elements</h2>
|
|
||||||
<div className={'bg-neutral-700 p-4 rounded shadow-lg border-t-4 border-primary-400'}>
|
|
||||||
<label className={'uppercase text-neutral-200'}>Email</label>
|
|
||||||
<input
|
|
||||||
type={'text'}
|
|
||||||
className={'w-full p-3 bg-neutral-600 border border-neutral-500 hover:border-neutral-400 text-sm rounded text-neutral-200 focus:shadow'}
|
|
||||||
style={{
|
|
||||||
transition: 'border-color 150ms linear, box-shadow 150ms ease-in',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<p className={'text-xs text-neutral-400 mt-2'}>
|
|
||||||
This is some descriptive helper text to explain how things work.
|
|
||||||
</p>
|
|
||||||
<div className={'mt-6'}/>
|
|
||||||
<label className={'uppercase text-neutral-200'}>Textarea</label>
|
|
||||||
<textarea
|
|
||||||
className={'w-full p-3 h-10 bg-neutral-600 border border-neutral-500 hover:border-neutral-400 text-sm rounded text-neutral-200 focus:shadow'}
|
|
||||||
style={{
|
|
||||||
transition: 'border-color 150ms linear, box-shadow 150ms ease-in',
|
|
||||||
}}
|
|
||||||
></textarea>
|
|
||||||
<div className={'mt-6'}/>
|
|
||||||
<button className={'tracking-wide bg-primary-500 spacing-wide text-xs text-primary-50 rounded p-3 uppercase border border-primary-600'}>
|
|
||||||
Button
|
|
||||||
</button>
|
|
||||||
<button className={'ml-2 tracking-wide bg-neutral-500 spacing-wide text-xs text-neutral-50 rounded p-3 uppercase border border-neutral-600'}>
|
|
||||||
Secondary
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import ContentBox from '@/components/elements/ContentBox';
|
||||||
|
|
||||||
|
export default class DesignElementsContainer extends React.PureComponent {
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div className={'my-10'}>
|
||||||
|
<div className={'flex'}>
|
||||||
|
<ContentBox className={'flex-1 mr-4'} title={'A Special Announcement'} borderColor={'border-primary-400'}>
|
||||||
|
<p className={'text-neutral-200 text-sm'}>
|
||||||
|
Your demands have been received: Dark Mode will be default in Pterodactyl 0.8!
|
||||||
|
</p>
|
||||||
|
<p><Link to={'/'}>Back</Link></p>
|
||||||
|
</ContentBox>
|
||||||
|
<div className={'ml-4 flex-1'}>
|
||||||
|
<h2 className={'text-neutral-300 mb-2 px-4'}>Form Elements</h2>
|
||||||
|
<div className={'bg-neutral-700 p-4 rounded shadow-lg border-t-4 border-primary-400'}>
|
||||||
|
<label className={'uppercase text-neutral-200'}>Email</label>
|
||||||
|
<input type={'text'} className={'input-dark'}/>
|
||||||
|
<p className={'input-help'}>
|
||||||
|
This is some descriptive helper text to explain how things work.
|
||||||
|
</p>
|
||||||
|
<div className={'mt-6'}/>
|
||||||
|
<label className={'uppercase text-neutral-200'}>Username</label>
|
||||||
|
<input type={'text'} className={'input-dark error'}/>
|
||||||
|
<p className={'input-help'}>
|
||||||
|
This field has an error.
|
||||||
|
</p>
|
||||||
|
<div className={'mt-6'}/>
|
||||||
|
<label className={'uppercase text-neutral-200'}>Disabled Field</label>
|
||||||
|
<input type={'text'} className={'input-dark'} disabled={true}/>
|
||||||
|
<div className={'mt-6'}/>
|
||||||
|
<label className={'uppercase text-neutral-200'}>Textarea</label>
|
||||||
|
<textarea className={'input-dark h-32'}></textarea>
|
||||||
|
<div className={'mt-6'}/>
|
||||||
|
<button className={'btn btn-primary btn-sm'}>
|
||||||
|
Blue
|
||||||
|
</button>
|
||||||
|
<button className={'btn btn-grey btn-sm ml-2'}>
|
||||||
|
Grey
|
||||||
|
</button>
|
||||||
|
<button className={'btn btn-green btn-sm ml-2'}>
|
||||||
|
Green
|
||||||
|
</button>
|
||||||
|
<button className={'btn btn-red btn-sm ml-2'}>
|
||||||
|
Red
|
||||||
|
</button>
|
||||||
|
<div className={'mt-6'}/>
|
||||||
|
<button className={'btn btn-secondary btn-sm'}>
|
||||||
|
Secondary
|
||||||
|
</button>
|
||||||
|
<button className={'btn btn-secondary btn-red btn-sm ml-2'}>
|
||||||
|
Secondary Danger
|
||||||
|
</button>
|
||||||
|
<div className={'mt-6'}/>
|
||||||
|
<button className={'btn btn-primary btn-lg'}>
|
||||||
|
Large
|
||||||
|
</button>
|
||||||
|
<button className={'btn btn-primary btn-xs ml-2'}>
|
||||||
|
Tiny
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { State, useStoreState } from 'easy-peasy';
|
||||||
|
import { ApplicationState } from '@/state/types';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [ isLoading, setIsLoading ] = useState(false);
|
||||||
|
const user = useStoreState((state: State<ApplicationState>) => state.user.data);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form className={'m-0'}>
|
||||||
|
<label htmlFor={'current_password'} className={'input-dark-label'}>Current Password</label>
|
||||||
|
<input
|
||||||
|
id={'current_password'}
|
||||||
|
type={'password'}
|
||||||
|
className={'input-dark'}
|
||||||
|
/>
|
||||||
|
<div className={'mt-6'}>
|
||||||
|
<label htmlFor={'new_password'} className={'input-dark-label'}>New Password</label>
|
||||||
|
<input
|
||||||
|
id={'new_password'}
|
||||||
|
type={'password'}
|
||||||
|
className={'input-dark'}
|
||||||
|
/>
|
||||||
|
<p className={'input-help'}>
|
||||||
|
Your new password must be at least 8 characters in length.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={'mt-6'}>
|
||||||
|
<label htmlFor={'new_password_confirm'} className={'input-dark-label'}>Confirm New Password</label>
|
||||||
|
<input
|
||||||
|
id={'new_password_confirm'}
|
||||||
|
type={'password'}
|
||||||
|
className={'input-dark'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={'mt-6'}>
|
||||||
|
<button className={'btn btn-primary btn-sm'} disabled={true}>
|
||||||
|
Update Password
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
18
resources/scripts/components/elements/ContentBox.tsx
Normal file
18
resources/scripts/components/elements/ContentBox.tsx
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
type Props = Readonly<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
|
||||||
|
title?: string;
|
||||||
|
borderColor?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default ({ title, borderColor, children, ...props }: Props) => (
|
||||||
|
<div {...props}>
|
||||||
|
{title && <h2 className={'text-neutral-300 mb-2 px-4'}>{title}</h2>}
|
||||||
|
<div className={classNames('bg-neutral-700 p-4 rounded shadow-lg', borderColor, {
|
||||||
|
'border-t-4': !!borderColor,
|
||||||
|
})}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
|
@ -1,10 +1,11 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Route, RouteComponentProps } from 'react-router-dom';
|
import { Route, RouteComponentProps } from 'react-router-dom';
|
||||||
import DesignElements from '@/components/account/DesignElements';
|
import DesignElementsContainer from '@/components/account/DesignElementsContainer';
|
||||||
|
import AccountOverviewContainer from '@/components/account/AccountOverviewContainer';
|
||||||
|
|
||||||
export default ({ match }: RouteComponentProps) => (
|
export default ({ match }: RouteComponentProps) => (
|
||||||
<div>
|
<div>
|
||||||
<Route path={`${match.path}/`} component={DesignElements} exact/>
|
<Route path={`${match.path}/`} component={AccountOverviewContainer} exact/>
|
||||||
<Route path={`${match.path}/design`} component={DesignElements} exact/>
|
<Route path={`${match.path}/design`} component={DesignElementsContainer} exact/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue