Skip to content
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
17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"start": "yarn storybook",
"docs": "build-storybook -c .storybook -o public",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
"build-storybook": "build-storybook",
"prettify": "prettier --config prettier.config.js --write 'src/**/*.{js,jsx,json,css,scss}'"
},
"repository": {
"type": "git",
Expand All @@ -35,7 +36,8 @@
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.0",
"@babel/runtime-corejs2": "^7.9.0",
"@storybook/addon-actions": "^5.3.17",
"@storybook/addon-actions": "^5.3.18",
"@storybook/addon-centered": "^5.3.18",
"@storybook/addon-knobs": "5.3.17",
"@storybook/addon-links": "^5.3.17",
"@storybook/addon-options": "5.3.17",
Expand All @@ -44,9 +46,18 @@
"@storybook/react": "^5.3.17",
"babel-loader": "^8.1.0",
"helix-ui": "^0.19.0",
"husky": "^4.2.5",
"prettier": "^2.0.4",
"prop-types": "^15.7.2",
"react": "^16.6.3",
"react-dom": "^16.6.3"
},
"dependencies": {}
"dependencies": {
"classnames": "^2.2.6"
},
"husky": {
"hooks": {
"pre-commit": "npm run prettify"
}
}
}
9 changes: 9 additions & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
arrowParens: 'always',
bracketSpacing: true,
printWidth: 100,
tabWidth: 2,
trailingComma: 'es5',
semi: true,
singleQuote: true,
};
87 changes: 37 additions & 50 deletions src/Button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,52 @@ import React from 'react';
import PropTypes from 'prop-types';
import Icon from '../Icon';

function cssFor (modifier) {
return {
'large': 'hxLg',
'primary': 'hxPrimary',
'small': 'hxSm',
'tertiary': 'hxTertiary',
}[modifier];
function cssFor(modifier) {
return {
large: 'hxLg',
primary: 'hxPrimary',
small: 'hxSm',
tertiary: 'hxTertiary',
}[modifier];
}

function classNames (props) {
return [
'hxBtn',
cssFor(props.variant),
cssFor(props.size),
props.className,
].join(' ').trim();
function classNames(props) {
return ['hxBtn', cssFor(props.variant), cssFor(props.size), props.className].join(' ').trim();
}

class Button extends React.Component {
render () {
// destructure props for JSX composition
const {
busy,
children, // explicity placed
className, // removed to prevent duplicate prop
headIcon,
size,
tailIcon,
type,
variant,
...props
} = this.props;
render() {
// destructure props for JSX composition
const {
busy,
children, // explicity placed
className, // removed to prevent duplicate prop
headIcon,
size,
tailIcon,
type,
variant,
...props
} = this.props;

return (
<button
className={classNames(this.props)}
type={type || 'button'}
{...props}
>
{headIcon && (<Icon type={headIcon} />)}
{children && (<span>{children}</span>)}
{busy ? (
<hx-busy></hx-busy>
) : (
tailIcon && (<Icon type={tailIcon}/>)
)}
</button>
);
}
return (
<button className={classNames(this.props)} type={type || 'button'} {...props}>
{headIcon && <Icon type={headIcon} />}
{children && <span>{children}</span>}
{busy ? <hx-busy></hx-busy> : tailIcon && <Icon type={tailIcon} />}
</button>
);
}
}

Button.propTypes = {
busy: PropTypes.bool,
disabled: PropTypes.bool,
headIcon: PropTypes.string,
size: PropTypes.string,
tailIcon: PropTypes.string,
type: PropTypes.string,
variant: PropTypes.string,
busy: PropTypes.bool,
disabled: PropTypes.bool,
headIcon: PropTypes.string,
size: PropTypes.string,
tailIcon: PropTypes.string,
type: PropTypes.string,
variant: PropTypes.string,
};

export default Button;
104 changes: 50 additions & 54 deletions src/Button/stories.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,57 @@
import Button from './';
import { Icons } from '../Icon';
import React from 'react';
import centered from '@storybook/addon-centered/react';
import { storiesOf } from '@storybook/react';
import { boolean, select, text } from '@storybook/addon-knobs/react';

const SIZES = {
'small': 'Small',
'': 'Medium',
'large': 'Large',
small: 'Small',
'': 'Medium',
large: 'Large',
};
const VARIANTS = {
'primary': 'Primary',
'': 'Secondary',
'tertiary': 'Tertiary',
primary: 'Primary',
'': 'Secondary',
tertiary: 'Tertiary',
};

storiesOf('Button', module)
.add('Sizes', () => {
.addDecorator(centered)
.add('Sizes', () => {
const size = select('size', SIZES, '');
return (
<Button
{ ...( size && { size }) }
>{SIZES[size]} Button</Button>
);
})
.add('Variants', () => {
return <Button {...(size && { size })}>{SIZES[size]} Button</Button>;
})
.add('Variants', () => {
const variant = select('variant', VARIANTS, '');
return (
<Button
{ ...(variant && { variant }) }
>{VARIANTS[variant]} Button</Button>
);
})
.add('Icon Only', () => {
return <Button {...(variant && { variant })}>{VARIANTS[variant]} Button</Button>;
})
.add('Icon Only', () => {
const headIcon = select('headIcon', Icons, 'download').trim();
return (<Button { ...( headIcon && { headIcon }) }/>);
})
.add('Icons and Text', () => {
return <Button {...(headIcon && { headIcon })} />;
})
.add('Icons and Text', () => {
const innerText = text('(innerText)', 'Action');
const headIcon = select('headIcon', ['', ...Icons], 'cog').trim();
const tailIcon = select('tailIcon', ['', ...Icons], 'angle-down').trim();

return (
<Button
{ ...( headIcon && { headIcon }) }
{ ...( tailIcon && { tailIcon }) }
>{innerText}</Button>
<Button {...(headIcon && { headIcon })} {...(tailIcon && { tailIcon })}>
{innerText}
</Button>
);
})
.add('Busy', () => {
})
.add('Busy', () => {
const innerText = text('(innerText)', 'Loading');
const busy = boolean('busy', true);
return (<Button { ...( busy && { busy }) }>{innerText}</Button>);
})
.add('Disabled', () => {
return <Button {...(busy && { busy })}>{innerText}</Button>;
})
.add('Disabled', () => {
const innerText = text('(innerText)', 'Loading');
const disabled = boolean('disabled', true);
return (<Button { ...( disabled && { disabled }) }>{innerText}</Button>)
})
.add('All Knobs', () => {
return <Button {...(disabled && { disabled })}>{innerText}</Button>;
})
.add('All Knobs', () => {
/* ========== KNOBS ========== */
let innerText = text('(innerText)', '');
let busy = boolean('busy', false);
Expand All @@ -70,26 +63,29 @@ storiesOf('Button', module)
let variant = select('variant', VARIANTS, '');

if (innerText.trim() === '') {
innerText = [
(busy ? 'Busy' : ''),
(disabled ? 'Disabled' : ''),
SIZES[size],
VARIANTS[variant],
'Button'
].join(' ').trim();
innerText = [
busy ? 'Busy' : '',
disabled ? 'Disabled' : '',
SIZES[size],
VARIANTS[variant],
'Button',
]
.join(' ')
.trim();
}

/* ========== OUTPUT ========== */
return (
<Button
{ ...( cssClasses && { className: cssClasses }) }
{ ...( busy && { busy }) }
{ ...( disabled && { disabled }) }
{ ...( headIcon && headIcon !== '' && { headIcon }) }
{ ...( size && { size }) }
{ ...( tailIcon && tailIcon !== '' && { tailIcon }) }
{ ...( variant && { variant }) }
>{innerText}</Button>
<Button
{...(cssClasses && { className: cssClasses })}
{...(busy && { busy })}
{...(disabled && { disabled })}
{...(headIcon && headIcon !== '' && { headIcon })}
{...(size && { size })}
{...(tailIcon && tailIcon !== '' && { tailIcon })}
{...(variant && { variant })}
>
{innerText}
</Button>
);
})
;
});
18 changes: 5 additions & 13 deletions src/Icon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,16 @@ import PropTypes from 'prop-types';
export const Icons = Object.keys(HelixUI.Utils.ICONS);

class Icon extends React.Component {
render () {
const {
type,
...props
} = this.props;
render() {
const { type, ...props } = this.props;

return (
<hx-icon
type={type}
{...props}
></hx-icon>
);
}
return <hx-icon type={type} {...props}></hx-icon>;
}
}

// additional configs here
Icon.propTypes = {
type: PropTypes.string,
type: PropTypes.string,
};

export default Icon;
8 changes: 5 additions & 3 deletions src/Icon/stories.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import Icon, { Icons } from './';
import centered from '@storybook/addon-centered/react';
import { select } from '@storybook/addon-knobs/react';
import { storiesOf } from '@storybook/react';

storiesOf('Icon', module)
.add('All Knobs', () => {
.addDecorator(centered)
.add('All Knobs', () => {
const type = select('type', Icons, 'bell');
return (<Icon type={type}/>);
});
return <Icon type={type} />;
});
43 changes: 43 additions & 0 deletions src/Select/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import classnames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';

const Select = ({ children, disabled, id, label, onChange, optional, required, ...rest }) => {
return (
<hx-select-control>
<select id={id} disabled={disabled} onChange={onChange} required={required} {...rest}>
{children}
</select>
<hx-select></hx-select>
{label && (
<label
className={classnames({
hxOptional: optional,
hxRequired: required,
})}
htmlFor={id}
>
{label}
</label>
)}
</hx-select-control>
);
};

Select.propTypes = {
children: PropTypes.node.isRequired,
disabled: PropTypes.bool.isRequired,
id: PropTypes.string.isRequired,
label: PropTypes.string,
onChange: PropTypes.func.isRequired,
optional: PropTypes.bool,
required: PropTypes.bool,
};

Select.defaultProps = {
disabled: false,
optional: false,
required: false,
};

export default Select;
Loading