Skip to content

Commit

Permalink
Create Button React components in UI Framework.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjcenizal committed Mar 28, 2017
1 parent 753327c commit 68e14a2
Show file tree
Hide file tree
Showing 31 changed files with 577 additions and 208 deletions.
10 changes: 6 additions & 4 deletions ui_framework/components/button/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@

.kuiButton--iconText {
.kuiButton__icon {
&:first-child {
margin-right: 4px;
$iconSpacing: 8px;

&:first-child:not(:only-child) {
margin-right: $iconSpacing;
}

&:last-child {
margin-left: 4px;
&:last-child:not(:only-child) {
margin-left: $iconSpacing;
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions ui_framework/components/button/basic_button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import classNames from 'classnames';

import { KuiButton } from './button';

const KuiBasicButton = props => {
const classes = classNames('kuiButton--basic', props.classes);

const extendedProps = Object.assign({}, props, {
classes,
});

return (
<KuiButton {...extendedProps} />
);
};

KuiBasicButton.propTypes = Object.assign({}, KuiButton.propTypes);

export { KuiBasicButton };
80 changes: 80 additions & 0 deletions ui_framework/components/button/button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, {
PropTypes,
} from 'react';

import classNames from 'classnames';
import keyMirror from 'keymirror';

const KuiButton = props => {
if (props.isSubmit) {
// input is a void element tag and can't have children.
if (typeof props.children !== 'string' || props.icon || props.rightIcon) {
throw new Error(
`KuiButton with isSubmit prop set to true can only accept string children, and can't
display icons. This is because input is a void element and can't contain children.`
);
}
}

function onClick() {
// onClick is optional, so exit early if it doesn't exist.
if (!props.onClick) {
return;
}
// Don't even trigger the onClick handler if we're disabled.
if (props.isDisabled) {
return;
}
props.onClick(props.data);
}

const classes = classNames('kuiButton', props.classes, {
'kuiButton--iconText': props.icon || props.iconRight,
});

let wrappedChildren;

if (props.children) {
// We need to wrap the text so that the icon's :first-child etc. seudo-selectors get applied
// correctly.
wrappedChildren = (
<span>{props.children}</span>
);
}

const elementType = props.isSubmit ? 'input' : props.href ? 'a' : 'button';

return React.createElement(elementType, {
'data-test-subj': props.testSubject,
className: classes,
href: props.href,
target: props.target,
type: props.isSubmit ? 'submit' : null,
disabled: props.isDisabled,
onClick,
value: props.isSubmit ? props.children : null,
children: props.isSubmit ? null : [props.icon, wrappedChildren, props.iconRight],
});
};

KuiButton.propTypes = {
testSubject: PropTypes.string,
data: PropTypes.any,
icon: PropTypes.node,
iconRight: PropTypes.node,
children: PropTypes.node,
type: PropTypes.string,
isSubmit: PropTypes.bool,
href: PropTypes.string,
target: PropTypes.string,
onClick: PropTypes.func,
isDisabled: PropTypes.bool,
hasIcon: PropTypes.bool,
classes: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array,
PropTypes.object,
]),
};

export { KuiButton };
24 changes: 24 additions & 0 deletions ui_framework/components/button/button_group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, {
PropTypes,
} from 'react';

import classNames from 'classnames';

const KuiButtonGroup = props => {
const classes = classNames('kuiButtonGroup', {
'kuiButtonGroup--united': props.isUnited,
});

return (
<div className={classes}>
{props.children}
</div>
);
};

KuiButtonGroup.propTypes = {
children: PropTypes.node,
isUnited: PropTypes.bool,
};

export { KuiButtonGroup };
49 changes: 49 additions & 0 deletions ui_framework/components/button/button_icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, {
PropTypes,
} from 'react';

import classNames from 'classnames';
import keyMirror from 'keymirror';

const KuiButtonIcon = props => {
const typeToIconClassMap = {
[KuiButtonIcon.TYPE.CREATE]: 'fa-plus',
[KuiButtonIcon.TYPE.DELETE]: 'fa-trash',
[KuiButtonIcon.TYPE.PREVIOUS]: 'fa-chevron-left',
[KuiButtonIcon.TYPE.NEXT]: 'fa-chevron-right',
};

let iconType;

if (props.type) {
iconType = typeToIconClassMap[props.type];

if (iconType === undefined) {
throw new Error(`KuiButtonIcon type not defined: ${props.type}`);
}
}

const iconClasses = classNames(
'kuiButton__icon kuiIcon',
iconType,
props.classes,
);

return (
<span className={iconClasses} />
);
};

KuiButtonIcon.TYPE = keyMirror({
CREATE: null,
DELETE: null,
PREVIOUS: null,
NEXT: null,
});

KuiButtonIcon.propTypes = {
type: PropTypes.string,
classes: PropTypes.string,
};

export { KuiButtonIcon };
20 changes: 20 additions & 0 deletions ui_framework/components/button/danger_button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import classNames from 'classnames';

import { KuiButton } from './button';

const KuiDangerButton = props => {
const classes = classNames('kuiButton--danger', props.classes);

const extendedProps = Object.assign({}, props, {
classes,
});

return (
<KuiButton {...extendedProps} />
);
};

KuiDangerButton.propTypes = Object.assign({}, KuiButton.propTypes);

export { KuiDangerButton };
20 changes: 20 additions & 0 deletions ui_framework/components/button/hollow_button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import classNames from 'classnames';

import { KuiButton } from './button';

const KuiHollowButton = props => {
const classes = classNames('kuiButton--hollow', props.classes);

const extendedProps = Object.assign({}, props, {
classes,
});

return (
<KuiButton {...extendedProps} />
);
};

KuiHollowButton.propTypes = Object.assign({}, KuiButton.propTypes);

export { KuiHollowButton };
6 changes: 6 additions & 0 deletions ui_framework/components/button/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { KuiBasicButton } from './basic_button';
export { KuiButtonGroup } from './button_group';
export { KuiButtonIcon } from './button_icon';
export { KuiDangerButton } from './danger_button';
export { KuiHollowButton } from './hollow_button';
export { KuiPrimaryButton } from './primary_button';
20 changes: 20 additions & 0 deletions ui_framework/components/button/primary_button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import classNames from 'classnames';

import { KuiButton } from './button';

const KuiPrimaryButton = props => {
const classes = classNames('kuiButton--primary', props.classes);

const extendedProps = Object.assign({}, props, {
classes,
});

return (
<KuiButton {...extendedProps} />
);
};

KuiPrimaryButton.propTypes = Object.assign({}, KuiButton.propTypes);

export { KuiPrimaryButton };
1 change: 1 addition & 0 deletions ui_framework/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './button';
8 changes: 4 additions & 4 deletions ui_framework/dist/ui_framework.css
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ body {
box-shadow: 0 0 0 1px #ffffff, 0 0 0 2px #6EADC1;
/* 3 */ }

.kuiButton--iconText .kuiButton__icon:first-child {
margin-right: 4px; }
.kuiButton--iconText .kuiButton__icon:first-child:not(:only-child) {
margin-right: 8px; }

.kuiButton--iconText .kuiButton__icon:last-child {
margin-left: 4px; }
.kuiButton--iconText .kuiButton__icon:last-child:not(:only-child) {
margin-left: 8px; }

/**
* 1. Override Bootstrap.
Expand Down
13 changes: 10 additions & 3 deletions ui_framework/doc_site/src/components/guide_demo/guide_demo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ export class GuideDemo extends Component {
}

update() {
// Inject HTML
// We'll just render the children if we have them.
if (this.props.children) {
return;
}

// Inject HTML.
this.content.innerHTML = this.props.html;

// Inject JS
// Inject JS.
const js = document.createElement('script');
js.type = 'text/javascript';
js.innerHTML = this.props.js;
this.content.appendChild(js);

// Inject CSS
// Inject CSS.
const css = document.createElement('style');
css.innerHTML = this.props.css;
this.content.appendChild(css);
Expand All @@ -38,12 +43,14 @@ export class GuideDemo extends Component {

return (
<div className={classes} ref={c => (this.content = c)}>
{this.props.children}
</div>
);
}
}

GuideDemo.propTypes = {
children: PropTypes.node,
js: PropTypes.string.isRequired,
html: PropTypes.string.isRequired,
css: PropTypes.string.isRequired,
Expand Down
9 changes: 0 additions & 9 deletions ui_framework/doc_site/src/views/button/button_basic.html

This file was deleted.

19 changes: 19 additions & 0 deletions ui_framework/doc_site/src/views/button/button_basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

import {
KuiBasicButton,
} from '../../../../components';

export default () => (
<div>
<KuiBasicButton>
Basic button
</KuiBasicButton>

<br />

<KuiBasicButton isDisabled>
Basic button, disabled
</KuiBasicButton>
</div>
);
9 changes: 0 additions & 9 deletions ui_framework/doc_site/src/views/button/button_danger.html

This file was deleted.

20 changes: 20 additions & 0 deletions ui_framework/doc_site/src/views/button/button_danger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

import {
KuiDangerButton,
} from '../../../../components';

export default () => (
<div>
<KuiDangerButton>
Danger button
</KuiDangerButton>

<br />

<KuiDangerButton isDisabled>
Danger button, disabled
</KuiDangerButton>
</div>

);
Loading

0 comments on commit 68e14a2

Please sign in to comment.