Convert LogIn to use shared Button
This commit is contained in:
parent
499c17ec86
commit
bda1ff13f4
5 changed files with 112 additions and 85 deletions
93
client/common/Button.jsx
Normal file
93
client/common/Button.jsx
Normal 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;
|
|
@ -2,10 +2,10 @@ import React from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { boolean, text } from '@storybook/addon-knobs';
|
import { boolean, text } from '@storybook/addon-knobs';
|
||||||
|
|
||||||
import Button from '.';
|
import Button from './Button';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Common/Button (JS)',
|
title: 'Common/Button',
|
||||||
component: Button
|
component: Button
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,3 +26,11 @@ export const SubmitButton = () => (
|
||||||
export const PrimaryButton = () => <Button label="login" onClick={action('onClick')}>Log In</Button>;
|
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 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>
|
||||||
|
);
|
|
@ -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>
|
|
|
@ -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;
|
|
|
@ -1,5 +1,8 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import Button from '../../../common/Button';
|
||||||
|
|
||||||
import { domOnlyProps } from '../../../utils/reduxFormUtils';
|
import { domOnlyProps } from '../../../utils/reduxFormUtils';
|
||||||
|
|
||||||
function LoginForm(props) {
|
function LoginForm(props) {
|
||||||
|
@ -30,7 +33,12 @@ function LoginForm(props) {
|
||||||
/>
|
/>
|
||||||
{password.touched && password.error && <span className="form-error">{password.error}</span>}
|
{password.touched && password.error && <span className="form-error">{password.error}</span>}
|
||||||
</p>
|
</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>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue