Inline button style (with/without icons)
This commit is contained in:
parent
7cf3a0bea0
commit
a2145ad979
2 changed files with 104 additions and 9 deletions
|
@ -6,6 +6,12 @@ import { Link } from 'react-router';
|
|||
import { remSize, prop } from '../theme';
|
||||
import Icon, { ValidIconNameType } from './Icon';
|
||||
|
||||
const kinds = {
|
||||
block: 'block',
|
||||
icon: 'icon',
|
||||
inline: 'inline',
|
||||
};
|
||||
|
||||
// The '&&&' will increase the specificity of the
|
||||
// component's CSS so that it overrides the more
|
||||
// general global styles
|
||||
|
@ -41,8 +47,74 @@ const StyledButton = styled.button`
|
|||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-right: ${remSize(8)};
|
||||
> * + * {
|
||||
margin-left: ${remSize(8)};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledInlineButton = styled.button`
|
||||
&&& {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
text-decoration: none;
|
||||
|
||||
color: ${prop('primaryTextColor')};
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
line-height: 1;
|
||||
|
||||
svg * {
|
||||
fill: ${prop('primaryTextColor')};
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
> * + * {
|
||||
margin-left: ${remSize(8)};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledIconButton = styled.button`
|
||||
&&& {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: ${remSize(32)}px;
|
||||
height: ${remSize(32)}px;
|
||||
text-decoration: none;
|
||||
|
||||
background-color: ${prop('buttonColorBackground')};
|
||||
color: ${prop('buttonColor')};
|
||||
cursor: pointer;
|
||||
border: 1px solid transparen;
|
||||
border-radius: 50%;
|
||||
padding: ${remSize(8)} ${remSize(25)};
|
||||
line-height: 1;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
color: ${prop('buttonHoverColor')};
|
||||
background-color: ${prop('buttonHoverColorBackground')};
|
||||
|
||||
svg * {
|
||||
fill: ${prop('buttonHoverColor')};
|
||||
}
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
color: ${prop('buttonDisabledColor')};
|
||||
background-color: ${prop('buttonDisabledColorBackground')};
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
> * + * {
|
||||
margin-left: ${remSize(8)};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -51,28 +123,39 @@ const StyledButton = styled.button`
|
|||
* A Button performs an primary action
|
||||
*/
|
||||
const Button = ({
|
||||
children, href, iconAfterName, iconBeforeName, label, to, type, ...props
|
||||
children, href, iconAfterName, iconBeforeName, kind, label, to, type, ...props
|
||||
}) => {
|
||||
const iconAfter = iconAfterName && <Icon name={iconAfterName} />;
|
||||
const iconBefore = iconBeforeName && <Icon name={iconBeforeName} />;
|
||||
const hasChildren = React.Children.count(children) > 0;
|
||||
|
||||
const content = <>{iconBefore}<span>{children}</span>{iconAfter}</>;
|
||||
const content = <>{iconBefore}{hasChildren && <span>{children}</span>}{iconAfter}</>;
|
||||
|
||||
let StyledComponent = StyledButton;
|
||||
|
||||
if (kind === kinds.inline) {
|
||||
StyledComponent = StyledInlineButton;
|
||||
} else if (kind === kinds.icon) {
|
||||
StyledComponent = StyledIconButton;
|
||||
}
|
||||
|
||||
if (href) {
|
||||
return <StyledButton as="a" aria-label={label} href={href} {...props}>{content}</StyledButton>;
|
||||
return <StyledComponent kind={kind} as="a" aria-label={label} href={href} {...props}>{content}</StyledComponent>;
|
||||
}
|
||||
|
||||
if (to) {
|
||||
return <StyledButton as={Link} aria-label={label} to={to} {...props}>{content}</StyledButton>;
|
||||
return <StyledComponent kind={kind} as={Link} aria-label={label} to={to} {...props}>{content}</StyledComponent>;
|
||||
}
|
||||
|
||||
return <StyledButton aria-label={label} type={type} {...props}>{content}</StyledButton>;
|
||||
return <StyledComponent kind={kind} aria-label={label} type={type} {...props}>{content}</StyledComponent>;
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
children: null,
|
||||
disabled: false,
|
||||
iconAfterName: null,
|
||||
iconBeforeName: null,
|
||||
kind: kinds.block,
|
||||
href: null,
|
||||
label: null,
|
||||
to: null,
|
||||
|
@ -80,13 +163,14 @@ Button.defaultProps = {
|
|||
};
|
||||
|
||||
Button.iconNames = Icon.names;
|
||||
Button.kinds = kinds;
|
||||
|
||||
Button.propTypes = {
|
||||
/**
|
||||
* The visible part of the button, telling the user what
|
||||
* the action is
|
||||
*/
|
||||
children: PropTypes.element.isRequired,
|
||||
children: PropTypes.element,
|
||||
/**
|
||||
If the button can be activated or not
|
||||
*/
|
||||
|
@ -95,11 +179,14 @@ Button.propTypes = {
|
|||
* Name of icon to place before child content
|
||||
*/
|
||||
iconAfterName: ValidIconNameType,
|
||||
|
||||
/**
|
||||
* Name of icon to place after child content
|
||||
*/
|
||||
iconBeforeName: ValidIconNameType,
|
||||
/**
|
||||
* The kind of button - determines how it appears visually
|
||||
*/
|
||||
kind: PropTypes.oneOf(Object.values(kinds)),
|
||||
/**
|
||||
* Specifying an href will use an <a> to link to the URL
|
||||
*/
|
||||
|
|
|
@ -42,3 +42,11 @@ export const ButtonWithIconBefore = () => (
|
|||
export const ButtonWithIconAfter = () => (
|
||||
<Button iconAfterName={Button.iconNames.github}>Create</Button>
|
||||
);
|
||||
|
||||
export const InlineButtonWithIconAfter = () => (
|
||||
<Button kind={Button.kinds.inline} iconAfterName={Button.iconNames.sortArrowDown}>File name</Button>
|
||||
);
|
||||
|
||||
export const InlineIconOnlyButton = () => (
|
||||
<Button kind={Button.kinds.inline} iconAfterName={Button.iconNames.plus} label="Add to collection" />
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue