Skip to content
This repository has been archived by the owner on Jun 5, 2023. It is now read-only.

Commit

Permalink
feat(Button): Add textOverflow prop
Browse files Browse the repository at this point in the history
  • Loading branch information
diondiondion committed Dec 7, 2020
1 parent c2f75d7 commit d5114e3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
7 changes: 7 additions & 0 deletions src/Button/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ menu: Components
---

import {Playground, Props} from 'docz';
import Box from '../Box';
import InlineList from '../InlineList';
import Button from './';

Expand Down Expand Up @@ -45,6 +46,12 @@ Nice looking buttons, yo.
<Button fullWidth align="left" size="large" color="shaded" icon="plus">
Add to My learning
</Button>
<br />
<Box width={285}>
<Button textOverflow="ellipsis" iconRight="chevron">
A Button with a very long label
</Button>
</Box>
</Playground>

## Props
Expand Down
44 changes: 38 additions & 6 deletions src/Button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styled, {css} from 'styled-components';

import {alpha} from '../utils/colors';
import {pxToRem} from '../utils/units';
import {fillParent} from '../mixins';
import {fillParent, ellipsis, overflowWrap} from '../mixins';
import {
getPropFilter,
getPropNamesFromPropDefinition,
Expand Down Expand Up @@ -221,20 +221,35 @@ const Content = styled.span`
justify-content: ${p => (p.align ? alignMap[p.align] : 'center')};
`;

const ButtonText = styled.span`
padding: 0 ${p => p.theme.globals.spacing.xxs};
/**
* The button label should just have some horinzontal spacing.
* But if `textOverflow="ellipsis" is set, the Button label
* will have overflow set to "hidden", which can cause the
* descenders of some characters (g, y, j) to be cut off.
* To avoid this, we also give the text label some vertical
* padding and visually remove it using negative margins.
*/

const ButtonText = styled.span.withConfig({
shouldForwardProp: prop => prop !== 'textOverflow',
})`
padding: ${p => p.theme.globals.spacing.xxs};
margin: -${p => p.theme.globals.spacing.xxs} 0;
vertical-align: middle;
${p => (p.textOverflow === 'ellipsis' ? ellipsis : overflowWrap)}
`;

const Button = forwardRef((props, ref) => {
const {
align,
as,
children,
color = 'default',
color,
icon,
iconRight,
fullWidth,
title,
textOverflow,
...otherProps
} = props;

Expand All @@ -248,6 +263,7 @@ const Button = forwardRef((props, ref) => {
aria-label={props['aria-label'] || title}
color={color}
align={align}
fullWidth={fullWidth || textOverflow === 'ellipsis'}
{...otherProps}
>
<HoverShade />
Expand All @@ -256,7 +272,11 @@ const Button = forwardRef((props, ref) => {
{icon && iconRight !== true && (
<Icon disablePointerEvents name={icon} />
)}
{children && <ButtonText>{children}</ButtonText>}
{children && (
<ButtonText textOverflow={textOverflow}>
{children}
</ButtonText>
)}
{iconRight && (
<Icon
disablePointerEvents
Expand All @@ -270,6 +290,11 @@ const Button = forwardRef((props, ref) => {

Button.displayName = 'Button';

Button.defaultProps = {
color: 'default',
textOverflow: 'wrap',
};

Button.propTypes = {
/**
* Renders the button in a "pressed" state.
Expand All @@ -293,7 +318,6 @@ Button.propTypes = {
* on the right.
*/
iconRight: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),

/**
* Render the button with fully rounded corners, useful for
* circular icon-only buttons.
Expand Down Expand Up @@ -326,6 +350,14 @@ Button.propTypes = {
* Align the button text
*/
align: PropTypes.oneOf(['left', 'right', 'center']),
/**
* Control whether long text labels wrap to a new line
* or are truncated with an ellipsis
* When set to 'ellipsis', the button will automatically
* enable the `fullWidth` prop and render as a block-level
* element that takes up all available width.
*/
textOverflow: PropTypes.oneOf(['wrap', 'ellipsis']),
};

// @component
Expand Down

0 comments on commit d5114e3

Please sign in to comment.