Convert LogIn to use shared Button

This commit is contained in:
Andrew Nicolaou 2020-04-19 17:12:55 +02:00
parent 499c17ec86
commit bda1ff13f4
5 changed files with 112 additions and 85 deletions

93
client/common/Button.jsx Normal file
View File

@ -0,0 +1,93 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { Link } from 'react-router';
import { remSize, prop } from '../theme';
// The '&&&' will increase the specificity of the
// component's CSS so that it overrides the more
// general global styles
const StyledButton = styled.button`
&&& {
display: flex;
justify-content: center;
align-items: center;
width: max-content;
text-decoration: none;
background-color: ${prop('buttonColorBackground')};
color: ${prop('buttonColor')};
cursor: pointer;
border: 2px solid ${prop('buttonBorderColor')};
border-radius: 2px;
padding: ${remSize(8)} ${remSize(25)};
line-height: 1;
&:hover:not(:disabled) {
color: ${prop('buttonHoverColor')};
background-color: ${prop('buttonHoverColorBackground')};
}
&:disabled {
color: ${prop('buttonDisabledColor')};
background-color: ${prop('buttonDisabledColorBackground')};
cursor: not-allowed;
}
}
`;
/**
* A Button performs an primary action
*/
const Button = ({
children, href, label, to, type, ...props
}) => {
if (href) {
return <StyledButton as="a" aria-label={label} href={href} {...props}>{children}</StyledButton>;
}
if (to) {
return <StyledButton as={Link} aria-label={label} to={to} {...props}>{children}</StyledButton>;
}
return <StyledButton aria-label={label} type={type} {...props}>{children}</StyledButton>;
};
Button.defaultProps = {
disabled: false,
href: null,
to: null,
type: 'button',
};
Button.propTypes = {
/**
* The visible part of the button, telling the user what
* the action is
*/
children: PropTypes.element.isRequired,
/**
If the button can be activated or not
*/
disabled: PropTypes.bool,
/**
* Specifying an href will use an <a> to link to the URL
*/
href: PropTypes.string,
/*
* An ARIA Label used for accessibility
*/
label: PropTypes.string.isRequired,
/**
* Specifying a to URL will use a react-router Link
*/
to: PropTypes.string,
/**
* If using a button, then type is defines the type of button
*/
type: PropTypes.oneOf(['button', 'submit']),
};
export default Button;

View File

@ -2,10 +2,10 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
import { boolean, text } from '@storybook/addon-knobs';
import Button from '.';
import Button from './Button';
export default {
title: 'Common/Button (JS)',
title: 'Common/Button',
component: Button
};
@ -26,3 +26,11 @@ export const SubmitButton = () => (
export const PrimaryButton = () => <Button label="login" onClick={action('onClick')}>Log In</Button>;
export const DisabledButton = () => <Button disabled label="login" onClick={action('onClick')}>Log In</Button>;
export const AnchorButton = () => (
<Button href="http://p5js.org" label="submit">Actually an anchor</Button>
);
export const ReactRouterLink = () => (
<Button to="./somewhere" label="submit">Actually a Link</Button>
);

View File

@ -1,32 +0,0 @@
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
import { action } from '@storybook/addon-actions';
import { boolean, text } from '@storybook/addon-knobs';
import Button from './';
<Meta title="Common/Button (MDX)" component={Button} />
# Button
A button is used to perform an action.
<Preview>
<Story name="All features">
<Button
disabled={boolean('disabled', false)}
type="submit"
label={text('label', 'submit')}
>
{text('children', 'this is the button')}
</Button>
</Story>
<Story name="Submit button">
<Button type="submit" label="submit" onClick={action('onClick')}>This is a submit button</Button>
</Story>
<Story name="Primary button">
<Button label="Log In" onClick={action('onClick')}>Log In</Button>
</Story>
<Story name="Disabled">
<Button disabled label="Log In" onClick={action('onClick')}>Log In</Button>
</Story>
</Preview>

View File

@ -1,50 +0,0 @@
import React from "react";
import PropTypes from "prop-types";
import styled from 'styled-components';
import { remSize, prop } from '../../theme';
const StyledButton = styled.button`
background-color: ${prop('buttonColorBackground')};
color: ${prop('buttonColor')};
cursor: pointer;
border: 2px solid ${prop('buttonBorderColor')};
border-radius: 2px;
padding: ${remSize(8)} ${remSize(25)};
line-height: 1;
margin: 0;
&:hover:not(:disabled) {
color: ${prop('buttonHoverColor')};
background-color: ${prop('buttonHoverColorBackground')};
}
&:disabled {
color: ${prop('buttonDisabledColor')};
background-color: ${prop('buttonDisabledColorBackground')};
cursor: not-allowed;
}
`;
/**
* This text will be used for the description in the story
*/
const Button = ({ children, label, ...props }) => {
return <StyledButton aria-label={label} {...props}>{children}</StyledButton>;
}
Button.propTypes = {
/**
* The visible part of the button
*/
children: PropTypes.element.isRequired,
/**
If the button can be clicked or not
*/
disabled: PropTypes.bool,
/*
* An ARIA Label used for accessibility
*/
label: PropTypes.string.isRequired,
};
export default Button;

View File

@ -1,5 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
import Button from '../../../common/Button';
import { domOnlyProps } from '../../../utils/reduxFormUtils';
function LoginForm(props) {
@ -30,7 +33,12 @@ function LoginForm(props) {
/>
{password.touched && password.error && <span className="form-error">{password.error}</span>}
</p>
<input type="submit" disabled={submitting || pristine} value="Log In" aria-label="login" />
<Button
aria-label="login"
type="submit"
disabled={submitting || pristine}
>Log In
</Button>
</form>
);
}