diff --git a/src/components/Button/Button-story.js b/src/components/Button/Button-story.js index 25db9a5dd7..48f216c50d 100644 --- a/src/components/Button/Button-story.js +++ b/src/components/Button/Button-story.js @@ -12,28 +12,29 @@ import { withKnobs, boolean, select } from '@storybook/addon-knobs'; import { iconAddSolid, iconSearch } from 'carbon-icons'; import AddFilled16 from '@carbon/icons-react/lib/add--filled/16'; import Search16 from '@carbon/icons-react/lib/search/16'; -import { settings } from 'carbon-components'; import Button from '../Button'; import ButtonSkeleton from '../Button/Button.Skeleton'; -import { componentsX } from '../../internal/FeatureFlags'; - -const { prefix } = settings; +import { breakingChangesX } from '../../internal/FeatureFlags'; const icons = { None: 'None', - 'Add with filled circle (iconAddSolid from `carbon-icons`)': componentsX - ? 'AddFilled16' - : 'iconAddSolid', - 'Search (iconSearch from `carbon-icons`)': componentsX - ? 'Search16' - : 'iconSearch', }; +if (breakingChangesX) { + icons['Add with filled circle (iconAddSolid from `carbon-icons`)'] = + 'iconAddSolid'; + icons['Search (iconSearch from `carbon-icons`)'] = 'iconSearch'; +} + +icons['Add with filled circle (AddFilled16 from `@carbon/icons`)'] = + 'AddFilled16'; +icons['Search (Search16 from `@carbon/icons`)'] = 'Search16'; + const iconMap = { iconAddSolid, iconSearch, - AddFilled16: , - Search16: , + AddFilled16, + Search16, }; const kinds = { @@ -45,23 +46,31 @@ const kinds = { }; const props = { - regular: () => ({ - className: 'some-class', - kind: select('Button kind (kind)', kinds, 'primary'), - disabled: boolean('Disabled (disabled)', false), - small: boolean('Small (small)', false), - icon: iconMap[select('Icon (icon)', icons, 'none')], - onClick: action('onClick'), - onFocus: action('onFocus'), - }), - set: () => ({ - className: 'some-class', - disabled: boolean('Disabled (disabled)', false), - small: boolean('Small (small)', false), - icon: iconMap[select('Icon (icon)', icons, 'none')], - onClick: action('onClick'), - onFocus: action('onFocus'), - }), + regular: () => { + const iconToUse = iconMap[select('Icon (icon)', icons, 'none')]; + return { + className: 'some-class', + kind: select('Button kind (kind)', kinds, 'primary'), + disabled: boolean('Disabled (disabled)', false), + small: boolean('Small (small)', false), + renderIcon: !iconToUse || iconToUse.svgData ? undefined : iconToUse, + icon: !iconToUse || !iconToUse.svgData ? undefined : iconToUse, + onClick: action('onClick'), + onFocus: action('onFocus'), + }; + }, + set: () => { + const iconToUse = iconMap[select('Icon (icon)', icons, 'none')]; + return { + className: 'some-class', + disabled: boolean('Disabled (disabled)', false), + small: boolean('Small (small)', false), + renderIcon: !iconToUse || iconToUse.svgData ? undefined : iconToUse, + icon: !iconToUse || !iconToUse.svgData ? undefined : iconToUse, + onClick: action('onClick'), + onFocus: action('onFocus'), + }; + }, }; const CustomLink = ({ children, href, ...other }) => ( diff --git a/src/components/Button/Button-test.js b/src/components/Button/Button-test.js index 7311eb389e..19d2cdd2e6 100644 --- a/src/components/Button/Button-test.js +++ b/src/components/Button/Button-test.js @@ -7,6 +7,7 @@ import React from 'react'; import { iconSearch } from 'carbon-icons'; +import Search16 from '@carbon/icons-react/lib/search/16'; import Button from '../Button'; import Link from '../Link'; import ButtonSkeleton from '../Button/Button.Skeleton'; @@ -121,8 +122,35 @@ describe('Button', () => { ); const icon = iconButton.find('svg'); + + it('should have the appropriate icon', () => { + expect(icon.hasClass('bx--btn__icon')).toBe(true); + }); + + it('should return error if icon given without description', () => { + const props = { + icon: 'search', + }; + // eslint-disable-next-line quotes + const error = new Error( + 'icon/renderIcon property specified without also providing an iconDescription property.' + ); + expect(Button.propTypes.iconDescription(props)).toEqual(error); + }); + }); + + describe('Renders custom icon buttons', () => { + const iconButton = mount( + + ); + const originalIcon = mount().find('svg'); + const icon = iconButton.find('svg'); + it('should have the appropriate icon', () => { expect(icon.hasClass('bx--btn__icon')).toBe(true); + expect(icon.children().html()).toBe(originalIcon.children().html()); }); it('should return error if icon given without description', () => { @@ -131,7 +159,7 @@ describe('Button', () => { }; // eslint-disable-next-line quotes const error = new Error( - 'icon property specified without also providing an iconDescription property.' + 'icon/renderIcon property specified without also providing an iconDescription property.' ); expect(Button.propTypes.iconDescription(props)).toEqual(error); }); diff --git a/src/components/Button/Button.js b/src/components/Button/Button.js index 31c1ea1336..0b374bf854 100644 --- a/src/components/Button/Button.js +++ b/src/components/Button/Button.js @@ -9,12 +9,15 @@ import PropTypes from 'prop-types'; import React from 'react'; import Icon from '../Icon'; import classNames from 'classnames'; +import warning from 'warning'; import { settings } from 'carbon-components'; import { ButtonTypes } from '../../prop-types/types'; -import { componentsX } from '../../internal/FeatureFlags'; +import { breakingChangesX } from '../../internal/FeatureFlags'; const { prefix } = settings; +let didWarnAboutDeprecation = false; + const Button = ({ children, as, @@ -26,6 +29,7 @@ const Button = ({ tabIndex, type, inputref, + renderIcon, icon, iconDescription, ...other @@ -46,23 +50,30 @@ const Button = ({ className: buttonClasses, ref: inputref, }; - const buttonImage = (() => { - if (componentsX && icon && React.isValidElement(icon)) { - return icon; - } - if (!componentsX && icon) { - return ( -