Skip to content
This repository has been archived by the owner on Mar 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #207 from tabler/form-shorthand-props
Browse files Browse the repository at this point in the history
Form components, features and fixes
  • Loading branch information
jonthomp authored Jun 5, 2018
2 parents 3ef2495 + 7281d2f commit 9a48d0e
Show file tree
Hide file tree
Showing 18 changed files with 283 additions and 66 deletions.
4 changes: 2 additions & 2 deletions example/src/FormElementsPage.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@ function FormElements() {
<Form.Group label="Input Group">
<Form.InputGroup>
<Form.Input placeholder="Search for..." />
<Form.InputGroup append>
<Form.InputGroupAppend>
<Button
RootComponent="a"
color="primary"
href="http://www.google.com"
>
Go!
</Button>
</Form.InputGroup>
</Form.InputGroupAppend>
</Form.InputGroup>
</Form.Group>
</ComponentDemo>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Button/Button.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type PropsForAll = {|
+to?: string,
+isOption?: boolean,
+rootRef?: (?HTMLElement) => void,
+onClick?: (event: SyntheticMouseEvent<HTMLElement>) => mixed,
|};

type DefaultButtonComponent = {|
Expand Down Expand Up @@ -70,6 +71,8 @@ const Button = (props: Props): React.Node => {
isDropdownToggle,
isOption,
rootRef,
to,
onClick,
} = props;

const classes = cn(
Expand Down Expand Up @@ -148,8 +151,6 @@ const Button = (props: Props): React.Node => {
</a>
);
} else {
const { onClick, to } = props;

const Component: React.ElementType = props.RootComponent;

return (
Expand All @@ -163,4 +164,6 @@ const Button = (props: Props): React.Node => {
Button.List = ButtonList;
Button.Dropdown = ButtonDropdown;

Button.displayName = "Button";

export default Button;
6 changes: 6 additions & 0 deletions src/components/Form/Form.examples.md
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@

```jsx
<Form onSubmit={(event) => console.log(event.target.name + 'clicked')}>
<Form.Input name='username' label='Username' placeholder='Enter Username' />
<Button type='submit' value='Submit' />
</Form>
```
2 changes: 1 addition & 1 deletion src/components/Form/Form.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import FormInputGroupPrepend from "./FormInputGroupPrepend.react";
import FormMaskedInput from "./FormMaskedInput.react";
import FormDatePicker from "./FormDatePicker.react";

type Props = {|
export type Props = {|
+children?: React.Node,
+className?: string,
+action?: string,
Expand Down
32 changes: 21 additions & 11 deletions src/components/Form/FormCheckbox.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import Form from "./";

export type Props = {|
+className?: string,
/**
* Wrap the checkbox with a label
*/
+label?: string,
+value?: string | number | boolean,
+name?: string,
Expand Down Expand Up @@ -33,23 +36,30 @@ function FormCheckbox({
{ "custom-control-inline": isInline },
className
);
return (
const inputComponent = (
<Form.Input
type="checkbox"
name={name}
value={value}
checked={checked}
className={classes}
disabled={disabled}
readOnly={readOnly}
onChange={onChange}
/>
);

return label ? (
<label className={classes}>
<Form.Input
type="checkbox"
name={name}
value={value}
checked={checked}
className={classes}
disabled={disabled}
readOnly={readOnly}
onChange={onChange}
/>
{inputComponent}
<span className="custom-control-label">{label}</span>
</label>
) : (
inputComponent
);
}

FormCheckbox.displayName = "Form.Checkbox";

/** @component */
export default FormCheckbox;
8 changes: 7 additions & 1 deletion src/components/Form/FormGroup.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@
import * as React from "react";
import cn from "classnames";
import FormLabel from "./FormLabel.react";
import FormInput from "./FormInput.react";
import type { Props as InputProps } from "./FormInput.react";

type Props = {|
+children?: React.Node,
+className?: string,
+label?: React.Node,
+isRequired?: boolean,
+inputProps?: InputProps,
|};

function FormGroup({
className,
children,
label,
isRequired,
inputProps,
}: Props): React.Node {
const classes = cn("form-group", className);
const inputComponent =
inputProps && React.createElement(FormInput, inputProps);
return (
<div className={classes}>
{!label ? null : typeof label === "string" ? (
Expand All @@ -28,7 +34,7 @@ function FormGroup({
) : (
label
)}
{children}
{inputComponent || children}
</div>
);
}
Expand Down
32 changes: 29 additions & 3 deletions src/components/Form/FormInput.examples.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
### Icon input
```jsx
<Form.Input name='username' placeholder='Username' />
```

#### Input Label
Render an input wrapped in a Form.Group with a Label

```jsx
<Form.Input label='username' placeholder='Username' />
```

is the same as

```jsx
<Form.Group>
<Form.Label>Username</Form.Label>
<Form.Input placeholder="Username" />
</Form.Group>
```

#### Input Icons

```jsx
<Form.Group label="Input Icon">
<Form.Input icon="user" placeholder="Username" />
</Form.Group>
```

#### Append the Icon

```jsx
<Form.Group label="Input Icon">
<Form.Input
icon="search"
placeholder="Search for..."
position="append"
className={"mb-3"}
/>
<Form.Input icon="user" placeholder="Username" />
</Form.Group>
```
13 changes: 12 additions & 1 deletion src/components/Form/FormInput.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as React from "react";
import { Icon } from "../";
import cn from "classnames";
import FormGroup from "./FormGroup.react";

type FormStyle = {|
+className?: string,
Expand Down Expand Up @@ -30,8 +31,15 @@ export type Props = {|
+placeholder?: string,
+type?: "checkbox" | "radio" | "text" | "email" | "password",
+value?: string | number | boolean,
/**
* Wraps the input in Form.Group and adds a label
*/
+label?: string,
|};

/**
* A an input field
*/
function FormInput(props: Props): React.Node {
const {
className,
Expand All @@ -50,6 +58,7 @@ function FormInput(props: Props): React.Node {
onBlur,
disabled,
readOnly,
label,
} = props;
const type = props.type || "text";

Expand Down Expand Up @@ -79,7 +88,7 @@ function FormInput(props: Props): React.Node {
onBlur,
};

return !icon ? (
const contents = !icon ? (
<React.Fragment>
{type === "checkbox" || type === "radio" ? (
<input {...allInputProps} checked={checked} />
Expand All @@ -106,6 +115,8 @@ function FormInput(props: Props): React.Node {
{feedback && <span className="invalid-feedback">{feedback}</span>}
</React.Fragment>
);

return label ? <FormGroup label={label}>{contents}</FormGroup> : contents;
}

FormInput.displayName = "Form.Input";
Expand Down
20 changes: 20 additions & 0 deletions src/components/Form/FormInputGroup.examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
```jsx
<Form.InputGroup append={<Button
RootComponent="a"
color="primary"
href="http://www.google.com"
>Go!
</Button>}>
<Form.Input placeholder="Search for..." />
</Form.InputGroup>
```

```jsx
<Form.InputGroup inputProps={{placeholder: "Search for..."}} append={<Button
RootComponent="a"
color="primary"
href="http://www.google.com"
>Go!
</Button>} />
```

40 changes: 27 additions & 13 deletions src/components/Form/FormInputGroup.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,46 @@

import * as React from "react";
import cn from "classnames";
import Form from "./Form.react";
import FormInputGroupAppend from "./FormInputGroupAppend.react";
import FormInputGroupPrepend from "./FormInputGroupPrepend.react";
import type { Props as InputProps } from "./FormInput.react";

type Props = {|
+children?: React.Node,
+className?: string,
+append?: boolean,
+prepend?: boolean,
+append?: React.Node,
+prepend?: React.Node,
+RootComponent?: React.ElementType,
+inputProps?: InputProps,
|};

function FormInputGroup({
className,
children,
append,
prepend,
RootComponent,
}: Props): React.Node {
function FormInputGroup(props: Props): React.Node {
const { className, append, prepend, RootComponent, inputProps } = props;
const classes = cn(
{
"input-group": !append && !prepend,
"input-group-append": append,
"input-group-prepend": prepend,
"input-group": true,
},
className
);
const Component = RootComponent || "div";
return <Component className={classes}>{children}</Component>;
const children = inputProps ? <Form.Input {...inputProps} /> : props.children;

if (prepend === true) {
return <FormInputGroupPrepend>{children}</FormInputGroupPrepend>;
}

if (append === true) {
return <FormInputGroupAppend>{children}</FormInputGroupAppend>;
}

return (
<Component className={classes}>
{prepend && <FormInputGroupPrepend>{prepend}</FormInputGroupPrepend>}
{children}
{append && <FormInputGroupAppend>{append}</FormInputGroupAppend>}
</Component>
);
}

FormInputGroup.displayName = "Form.InputGroup";
Expand Down
14 changes: 14 additions & 0 deletions src/components/Form/FormInputGroupAppend.examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```jsx
<Form.InputGroup>
<Form.Input placeholder="Search for..." />
<Form.InputGroupAppend>
<Button
RootComponent="a"
color="primary"
href="http://www.google.com"
>
Go!
</Button>
</Form.InputGroupAppend>
</Form.InputGroup>
```
9 changes: 2 additions & 7 deletions src/components/Form/FormInputGroupAppend.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@

import * as React from "react";
import cn from "classnames";
import FormInputGroup from "./FormInputGroup.react";

type Props = {|
+children?: React.Node,
+className?: string,
|};

function FormInputGroupAppend({ className, children }: Props): React.Node {
const classes = cn(className);
return (
<FormInputGroup RootComponent="span" className={classes} append>
<span className="input-group-text">{children}</span>
</FormInputGroup>
);
const classes = cn("input-group-append", className);
return <span className={classes}>{children}</span>;
}

FormInputGroupAppend.displayName = "Form.InputGroupAppend";
Expand Down
14 changes: 14 additions & 0 deletions src/components/Form/FormInputGroupPrepend.examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```jsx
<Form.InputGroup>
<Form.InputGroupPrepend>
<Button
RootComponent="a"
color="primary"
href="http://www.google.com"
>
Go!
</Button>
</Form.InputGroupPrepend>
<Form.Input placeholder="Search for..." />
</Form.InputGroup>
```
Loading

0 comments on commit 9a48d0e

Please sign in to comment.