diff --git a/spec/pivotal-ui-react/alerts/alerts_spec.js b/spec/pivotal-ui-react/alerts/alerts_spec.js index 1547762b9..23ebff748 100644 --- a/spec/pivotal-ui-react/alerts/alerts_spec.js +++ b/spec/pivotal-ui-react/alerts/alerts_spec.js @@ -38,8 +38,8 @@ describe('Alert Component', () => { it('has a close button', () => { expect('.pui-alert button').toHaveLength(1); - expect('.pui-btn-default-flat.pui-btn-icon').toHaveClass('pui-alert-close-btn'); - expect('.pui-btn-default-flat.pui-btn-icon .icon-close').toExist(); + expect('.pui-btn--default.pui-btn--flat.pui-btn--icon').toHaveClass('pui-alert-close-btn'); + expect('.pui-btn--default.pui-btn--flat.pui-btn--icon .icon-close').toExist(); }); it('has an sr-only close button', () => { diff --git a/spec/pivotal-ui-react/buttons/buttons_spec.js b/spec/pivotal-ui-react/buttons/buttons_spec.js index aef201888..d20c58fb9 100644 --- a/spec/pivotal-ui-react/buttons/buttons_spec.js +++ b/spec/pivotal-ui-react/buttons/buttons_spec.js @@ -11,8 +11,8 @@ describe('UIButton', () => { it('creates a button', () => { expect('button').toHaveClass('pui-btn'); - expect('button').toHaveClass('pui-btn-default'); - expect('button').toHaveText('Click here'); + expect('button').toHaveClass('pui-btn--default'); + expect('button .pui-btn__inner-content').toHaveText('Click here'); }); describe('when href attribute is set', () => { @@ -135,7 +135,7 @@ describe('UIButton', () => { }); it('adds the kind class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-default'); + expect('button.pui-btn').toHaveClass('pui-btn--default'); }); }); @@ -145,7 +145,7 @@ describe('UIButton', () => { }); it('adds the kind class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-danger'); + expect('button.pui-btn').toHaveClass('pui-btn--danger'); }); }); @@ -155,7 +155,7 @@ describe('UIButton', () => { }); it('adds the kind class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-brand'); + expect('button.pui-btn').toHaveClass('pui-btn--brand'); }); }); @@ -165,7 +165,7 @@ describe('UIButton', () => { }); it('adds the kind class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-primary'); + expect('button.pui-btn').toHaveClass('pui-btn--primary'); }); }); @@ -175,7 +175,7 @@ describe('UIButton', () => { }); it('adds the large button class', () => { - expect('button.pui-btn').toHaveClass('pui-btn-lg'); + expect('button.pui-btn').toHaveClass('pui-btn--lg'); }); }); @@ -185,7 +185,7 @@ describe('UIButton', () => { }); it('adds the large button class', () => { - expect('button.pui-btn').toHaveClass('pui-btn-full'); + expect('button.pui-btn').toHaveClass('pui-btn--full'); }); }); @@ -195,7 +195,7 @@ describe('UIButton', () => { }); it('adds the large button class', () => { - expect('button.pui-btn').toHaveClass('pui-btn-sm'); + expect('button.pui-btn').toHaveClass('pui-btn--sm'); }); }); @@ -205,7 +205,7 @@ describe('UIButton', () => { }); it('adds the large button class', () => { - expect('button.pui-btn').toHaveClass('pui-btn-icon'); + expect('button.pui-btn').toHaveClass('pui-btn--icon'); }); }); @@ -214,44 +214,8 @@ describe('UIButton', () => { subject::setProps({alt: true}); }); - describe('when kind is default', () => { - beforeEach(() => { - subject::setProps({kind: 'default'}); - }); - - it('adds appropriate alt class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-default-alt'); - }); - }); - - describe('when kind is danger', () => { - beforeEach(() => { - subject::setProps({kind: 'danger'}); - }); - - it('adds appropriate alt class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-danger-alt'); - }); - }); - - describe('when kind is brand', () => { - beforeEach(() => { - subject::setProps({kind: 'brand'}); - }); - - it('adds appropriate alt class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-brand-alt'); - }); - }); - - describe('when kind is primary', () => { - beforeEach(() => { - subject::setProps({kind: 'primary'}); - }); - - it('adds appropriate alt class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-primary-alt'); - }); + it('adds appropriate alt class to the button', () => { + expect('button.pui-btn').toHaveClass('pui-btn--alt'); }); }); @@ -260,44 +224,8 @@ describe('UIButton', () => { subject::setProps({flat: true}); }); - describe('when kind is default', () => { - beforeEach(() => { - subject::setProps({kind: 'default'}); - }); - - it('adds appropriate flat class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-default-flat'); - }); - }); - - describe('when kind is danger', () => { - beforeEach(() => { - subject::setProps({kind: 'danger'}); - }); - - it('adds appropriate flat class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-danger-flat'); - }); - }); - - describe('when kind is brand', () => { - beforeEach(() => { - subject::setProps({kind: 'brand'}); - }); - - it('adds appropriate flat class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-brand-flat'); - }); - }); - - describe('when kind is primary', () => { - beforeEach(() => { - subject::setProps({kind: 'primary'}); - }); - - it('adds appropriate flat class to the button', () => { - expect('button.pui-btn').toHaveClass('pui-btn-primary-flat'); - }); + it('adds appropriate flat class to the button', () => { + expect('button.pui-btn').toHaveClass('pui-btn--flat'); }); }); diff --git a/spec/pivotal-ui-react/flyout/flyout_spec.js b/spec/pivotal-ui-react/flyout/flyout_spec.js index e918bb27f..7df606360 100644 --- a/spec/pivotal-ui-react/flyout/flyout_spec.js +++ b/spec/pivotal-ui-react/flyout/flyout_spec.js @@ -45,8 +45,9 @@ describe('Flyout', () => { }); it('renders an icon button', () => { - expect('.pui-dialog .pui-flyout-icon-btn').toHaveClass('pui-btn-default-flat'); - expect('.pui-dialog .pui-flyout-icon-btn').toHaveClass('pui-btn-icon'); + expect('.pui-dialog .pui-flyout-icon-btn').toHaveClass('pui-btn--default'); + expect('.pui-dialog .pui-flyout-icon-btn').toHaveClass('pui-btn--flat'); + expect('.pui-dialog .pui-flyout-icon-btn').toHaveClass('pui-btn--icon'); expect('.pui-dialog .pui-flyout-icon-btn').toHaveAttr('aria-label', 'Close'); expect(Icon).toHaveBeenRenderedWithProps({ src: 'chevron_left', @@ -102,7 +103,7 @@ describe('Flyout', () => { }); it('renders the specified icon', () => { - expect('.pui-flyout-header.grid > .col.col-fixed .pui-btn.pui-btn-default-flat.pui-btn-icon .icon.icon-middle .icon-chevron_left').toHaveText(''); + expect('.pui-flyout-header.grid > .col.col-fixed .icon.icon-middle .icon-chevron_left').toExist(); }); describe('when clicking the icon button', () => { @@ -127,7 +128,7 @@ describe('Flyout', () => { }); it('renders that icon instead of the close icon', () => { - expect(`.pui-flyout-header.grid > .col.col-fixed .pui-btn.pui-btn-default-flat.pui-btn-icon .icon.icon-middle .icon-${iconSrc}`).toHaveText(''); + expect(`.pui-flyout-header.grid > .col.col-fixed .icon.icon-middle .icon-${iconSrc}`).toExist(); }); }); }); diff --git a/spec/pivotal-ui-react/modal/modal_spec.js b/spec/pivotal-ui-react/modal/modal_spec.js index de1eff133..a56fad33d 100644 --- a/spec/pivotal-ui-react/modal/modal_spec.js +++ b/spec/pivotal-ui-react/modal/modal_spec.js @@ -45,8 +45,9 @@ describe('Modal', () => { it('renders a close button', () => { expect('.pui-dialog.pui-modal-dialog .pui-modal-close-btn').toHaveAttr('aria-label', 'Close'); - expect('.pui-dialog.pui-modal-dialog .pui-modal-close-btn').toHaveClass('pui-btn-default-flat'); - expect('.pui-dialog.pui-modal-dialog .pui-modal-close-btn').toHaveClass('pui-btn-icon'); + expect('.pui-dialog.pui-modal-dialog .pui-modal-close-btn').toHaveClass('pui-btn--default'); + expect('.pui-dialog.pui-modal-dialog .pui-modal-close-btn').toHaveClass('pui-btn--flat'); + expect('.pui-dialog.pui-modal-dialog .pui-modal-close-btn').toHaveClass('pui-btn--icon'); expect(Icon).toHaveBeenRenderedWithProps({src: 'close', size: 'inherit', style: {}, verticalAlign: 'middle'}); }); diff --git a/spec/pivotal-ui-react/pagination/pagination_spec.js b/spec/pivotal-ui-react/pagination/pagination_spec.js index f50824ba0..2a51533df 100644 --- a/spec/pivotal-ui-react/pagination/pagination_spec.js +++ b/spec/pivotal-ui-react/pagination/pagination_spec.js @@ -29,9 +29,9 @@ describe('Pagination', () => { }); it('renders all buttons with flat class', () => { - expect('.pagination .pui-btn:eq(0)').toHaveClass('pui-btn-default-flat'); - expect('.pagination .pui-btn:eq(1)').toHaveClass('pui-btn-brand-flat'); - expect('.pagination .pui-btn:eq(2)').toHaveClass('pui-btn-default-flat'); + expect('.pagination .pui-btn:eq(0)').toHaveClass(['pui-btn--default', 'pui-btn--flat']); + expect('.pagination .pui-btn:eq(1)').toHaveClass(['pui-btn--brand', 'pui-btn--flat']); + expect('.pagination .pui-btn:eq(2)').toHaveClass(['pui-btn--default', 'pui-btn--flat']); }); describe('props', () => { @@ -63,7 +63,7 @@ describe('Pagination', () => { it('renders an active .pui-btn when activePage number is specified', () => { renderComponent({activePage: 1}); - expect('.pagination .pui-btn:eq(1)').toHaveClass('pui-btn-brand-flat'); + expect('.pagination .pui-btn:eq(1)').toHaveClass(['pui-btn--brand', 'pui-btn--flat']); expect('.pagination .pui-btn:eq(1)').toHaveClass('active'); }); diff --git a/spec/pivotal-ui-react/wizard/wizard_spec.js b/spec/pivotal-ui-react/wizard/wizard_spec.js index 69c197ccb..3a267927a 100644 --- a/spec/pivotal-ui-react/wizard/wizard_spec.js +++ b/spec/pivotal-ui-react/wizard/wizard_spec.js @@ -234,7 +234,7 @@ describe('Wizard', () => { }); it('renders a cancel button', () => { - expect('.wizard-cancel-btn.pui-btn-primary-alt').toHaveText('Cancel'); + expect('.wizard-cancel-btn.pui-btn--primary.pui-btn--alt').toHaveText('Cancel'); }); describe('with custom cancel text', () => { @@ -243,7 +243,7 @@ describe('Wizard', () => { }); it('renders a cancel button with custom text', () => { - expect('.wizard-cancel-btn.pui-btn-primary-alt').toHaveText('Close'); + expect('.wizard-cancel-btn.pui-btn--primary.pui-btn--alt').toHaveText('Close'); }); }); }); @@ -253,7 +253,7 @@ describe('Wizard', () => { }); it('renders a "next" PrimaryButton', () => { - expect('.wizard-next-btn.pui-btn-primary').toHaveText('Next'); + expect('.wizard-next-btn.pui-btn--primary').toHaveText('Next'); }); it('checks if the next button is enabled', () => { @@ -279,7 +279,7 @@ describe('Wizard', () => { }); it('does not render the next button', () => { - expect('.wizard-next-btn.pui-btn-primary').not.toExist(); + expect('.wizard-next-btn.pui-btn--primary').not.toExist(); }); }); @@ -290,7 +290,7 @@ describe('Wizard', () => { }); it('renders the custom text', () => { - expect('.wizard-next-btn.pui-btn-primary').toHaveText('customNext'); + expect('.wizard-next-btn.pui-btn--primary').toHaveText('customNext'); }); }); @@ -306,7 +306,7 @@ describe('Wizard', () => { }); it('disables the "next" button', () => { - expect('.wizard-next-btn.pui-btn-primary').toHaveAttr('disabled'); + expect('.wizard-next-btn.pui-btn--primary').toHaveAttr('disabled'); }); }); }); @@ -317,7 +317,7 @@ describe('Wizard', () => { }); it('renders a "finish" PrimaryButton', () => { - expect('.wizard-finish-btn.pui-btn-primary').toHaveText('Finish'); + expect('.wizard-finish-btn.pui-btn--primary').toHaveText('Finish'); }); describe('when "hideFinishButton" is true', () => { @@ -345,11 +345,11 @@ describe('Wizard', () => { }); it('does not render a "next" PrimaryButton', () => { - expect('.wizard-next-btn.pui-btn-primary').not.toExist(); + expect('.wizard-next-btn.pui-btn--primary').not.toExist(); }); it('renders a "back" alt PrimaryButton', () => { - expect('.wizard-back-btn.pui-btn-primary-alt').toHaveText('Back'); + expect('.wizard-back-btn.pui-btn--primary.pui-btn--alt').toHaveText('Back'); }); describe('when clicking the "back" button', () => { @@ -370,7 +370,7 @@ describe('Wizard', () => { }); it('renders the custom text', () => { - expect('.wizard-finish-btn.pui-btn-primary').toHaveText('customFinish'); + expect('.wizard-finish-btn.pui-btn--primary').toHaveText('customFinish'); }); }); diff --git a/src/react/buttons/buttons.js b/src/react/buttons/buttons.js index 46da35c0c..ab9ea45db 100644 --- a/src/react/buttons/buttons.js +++ b/src/react/buttons/buttons.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {mergeProps} from '../helpers'; +import classnames from 'classnames'; export class UIButton extends React.Component { static propTypes = { @@ -26,28 +26,29 @@ export class UIButton extends React.Component { } render() { - const {alt, flat, icon, iconPosition, iconOnly, large, small, kind, children, fullWidth, ...others} = this.props; + const {alt, className, flat, icon, iconPosition, iconOnly, large, small, kind, children, fullWidth, ...others} = this.props; if (iconOnly && !others['aria-label'] && process.env.NODE_ENV === 'development') { console.error('Icon-only buttons should have an accessible title set via the "aria-label" prop.'); } - const buttonClasses = { - className: [ + let props = { + className: classnames( + className, + 'pui-btn', + `pui-btn--${kind}`, { - 'pui-btn': true, - [`pui-btn-${kind}-alt`]: alt, - [`pui-btn-${kind}-flat`]: flat, - [`pui-btn-${kind}`]: !alt && !flat, - 'pui-btn-lg': large, - 'pui-btn-sm': small, - 'pui-btn-icon': iconOnly, - 'pui-btn-icon-right': !!icon && iconPosition === 'right', - 'pui-btn-full': fullWidth + 'pui-btn--alt': alt, + 'pui-btn--flat': flat, + 'pui-btn--lg': large, + 'pui-btn--sm': small, + 'pui-btn--icon': iconOnly, + 'pui-btn--icon-right': !!icon && iconPosition === 'right', + 'pui-btn--full': fullWidth } - ] + ), + ...others }; - let props = mergeProps(others, buttonClasses); const buttonText = Array.isArray(children) ? children.filter(child => typeof child === 'string').join(' ') : @@ -56,32 +57,23 @@ export class UIButton extends React.Component { let btnChildren = children; if (buttonText && !iconOnly) { - props = mergeProps(props, {'aria-label': buttonText}); + props = {'aria-label': buttonText, ...props}; btnChildren = ({children}); } - let buttonContent = ( - - {icon} - {btnChildren} - ); - - if (iconPosition === 'right') { - buttonContent = ( - - {btnChildren} - {icon} - ); - } - - return this.props.href ? - {buttonContent} : - ; + const buttonContent = ( + + {iconPosition === 'right' ? btnChildren : icon} + {iconPosition === 'right' ? icon : btnChildren} + + ); + return this.props.href + ? {buttonContent} + : ; } } + const defButton = propOverrides => { return class extends React.Component { render() {