Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add forms #17

Merged
merged 5 commits into from
Oct 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"dependencies": {
"babel-polyfill": "~6.13.0",
"classnames": "^2.2.5",
"react": "~15.3.0",
"react-dom": "~15.3.0"
},
Expand Down
11 changes: 11 additions & 0 deletions src/components/CurrencyInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { InputGroup, InputGroupAddon, Input } from 'reactstrap';

const CurrencyInput = ({ type, size, ...props }) => (
<InputGroup size={size}>
<InputGroupAddon>$</InputGroupAddon>
<Input {...props} />
</InputGroup>
);

export default CurrencyInput;
39 changes: 39 additions & 0 deletions src/components/FormChoice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import classname from 'classnames';
import { FormGroup, Input, Label } from 'reactstrap';

const FormChoice = props => {
const {
inline,
color,
state,
disabled,
children,
type,
...attributes
} = props;

const labelClasses = classname({ 'form-check-inline': inline })
, item = (
<Label className={labelClasses} check={!inline}>
<Input type={type} {...attributes} disabled={disabled} />
<span children={children} />
</Label>
);

if (type === 'select') {
return <option {...attributes} children={children} />
} else if (inline) {
return item;
} else {
return (
<FormGroup
check
color={color || state}
disabled={disabled}
children={item} />
);
}
}

export default FormChoice;
79 changes: 79 additions & 0 deletions src/components/FormRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react';
import { FormGroup, Input, Label, Col, FormFeedback, FormText } from 'reactstrap';

const FormRow = props => {
const {
id,
size,
label,
color,
state,
hint,
feedback,
required,
type,
children,
inline,
...attributes
} = props;

let content;

if (type === 'radio' || type === 'checkbox') {
content = React.Children.map(children, child => React.cloneElement(child, {
type,
inline,
...attributes
}));
} else {
const InputElement = (typeof type === 'string') ? Input : type;
content = (
<InputElement
id={id}
size={size}
state={color || state}
type={type}
children={React.Children.map(children, child => React.cloneElement(child, { type }))}
{...attributes}
/>
);
}

return (
<FormGroup row color={color || state}>
<Label for={id} sm={3} size={size}>
{ label }
{ required && label ? <span className="text-danger"> *</span> : null }
</Label>
<Col sm={9}>
{ content }
{ hint ? <FormText color="muted" children={hint} /> : null }
{ feedback ? <FormFeedback children={feedback} /> : null }
</Col>
</FormGroup>
);
};

FormRow.propTypes = {
label: React.PropTypes.string,
hint: React.PropTypes.string,
feedback: React.PropTypes.string,
required: React.PropTypes.bool,
type: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.element,
React.PropTypes.func
]),
inline: React.PropTypes.bool
};

FormRow.defaultProps = {
label: '',
hint: '',
feedback: '',
required: false,
type: 'text',
inline: false
};

export default FormRow;
59 changes: 59 additions & 0 deletions stories/Forms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';
import { Container, Input } from 'reactstrap';
import { storiesOf } from '@kadira/storybook';

import FormRow from '../src/components/FormRow';
import FormChoice from '../src/components/FormChoice';
import CurrencyInput from '../src/components/CurrencyInput';

storiesOf('Forms', module)
.add('Inputs', () => (
<Container className="m-t-3">
<h1 className="display-4 m-b-3">Inputs</h1>
<p className="lead">An <code>Input</code> is the simplest unit for building forms.</p>

<h2 className="m-y-3">Default (Text) Input</h2>
<Input placeholder="I'm a placeholder!" />

<h2 className="m-y-3">Custom Inputs</h2>
<p>Currency</p>
<CurrencyInput />
</Container>
))
.add('Form Rows', () => (
<Container className="m-t-3">
<h1 className="display-4 m-b-3">Form Rows</h1>
<p className="lead">A <code>FormRow</code> combines a label and an input with an interface to provide feedback, hints, and can specify whether or not the field is required.</p>

<h2 className="m-y-3">Example</h2>
<FormRow label="First Name" />
<FormRow label="Last Name" feedback="can't be blank" color="danger" />
<FormRow label="Nickname" hint="A fun name to describe yourself!" />
<FormRow label="DOB" required />
<FormRow label="Disabled Field" disabled />
<FormRow state="warning" placeholder="Labels can be omitted but that may be bad"/>
<FormRow type="textarea" label="Notes" />
<FormRow type="select" label="Select Movie" color="success" feedback="Awesome!">
<FormChoice value="override">A New Hope</FormChoice>
<FormChoice>The Empire Strikes Back</FormChoice>
<FormChoice>The Force Awakens</FormChoice>
</FormRow>
<FormRow type="radio" label="Select Ship" hint="Some ships are unreliable..." name="ship">
<FormChoice color="danger">Death Star</FormChoice>
<FormChoice color="warning">Millennium Falcon</FormChoice>
<FormChoice color="success">Imperial Shuttle</FormChoice>
</FormRow>
<FormRow type="checkbox" label="Select the character(s) you like">
<FormChoice>Darth Vader</FormChoice>
<FormChoice>Luke Skywalker</FormChoice>
<FormChoice disabled>Emperor Palpatine</FormChoice>
<FormChoice>Rey</FormChoice>
<FormChoice>TK-421</FormChoice>
</FormRow>
<FormRow type="radio" label="Do you like Star Wars?" inline name="movie">
<FormChoice>Yes</FormChoice>
<FormChoice disabled>No</FormChoice>
</FormRow>
<FormRow type={CurrencyInput} label="How much would you pay to meet the cast?" />
</Container>
));
1 change: 1 addition & 0 deletions stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import './Alerts';
import './Buttons';
import './Datapair';
import './DateMonth';
import './Forms';
import './HelpBubble';