diff --git a/components/button/__tests__/__snapshots__/icon.test.tsx.snap b/components/button/__tests__/__snapshots__/icon.test.tsx.snap new file mode 100644 index 000000000..07c328837 --- /dev/null +++ b/components/button/__tests__/__snapshots__/icon.test.tsx.snap @@ -0,0 +1,189 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ButtonIcon should render correctly 1`] = ` +"" +`; + +exports[`ButtonIcon should work with right 1`] = ` +"" +`; diff --git a/components/button/__tests__/icon.test.tsx b/components/button/__tests__/icon.test.tsx new file mode 100644 index 000000000..02470d6a0 --- /dev/null +++ b/components/button/__tests__/icon.test.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import { mount } from 'enzyme' +import { Button } from 'components' +const Icon: React.FC = () => + +describe('ButtonIcon', () => { + it('should render correctly', () => { + const wrapper = mount() + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('should work with right', () => { + const wrapper = mount() + expect(wrapper.html()).toMatchSnapshot() + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('the width of the text should be filled', () => { + const autoWrapper = mount( + , + ) + const wrapper = mount() + + const autoHtml = autoWrapper.find('.text').html() + const html = wrapper.find('.text').html() + expect(html).not.toEqual(autoHtml) + + const mini = mount() + const miniIcon = mount( + , + ) + const miniHtml = mini.find('.text').html() + const miniIconHtml = miniIcon.find('.text').html() + expect(miniHtml).not.toEqual(miniIconHtml) + }) +}) diff --git a/components/button/__tests__/index.test.tsx b/components/button/__tests__/index.test.tsx index babf27927..a11dce02d 100644 --- a/components/button/__tests__/index.test.tsx +++ b/components/button/__tests__/index.test.tsx @@ -1,6 +1,6 @@ import React from 'react' import { mount } from 'enzyme' -import { Button } from '../../' +import { Button } from 'components' import { sleep } from 'tests/utils' describe('Button', () => { diff --git a/components/button/button-icon.tsx b/components/button/button-icon.tsx new file mode 100644 index 000000000..f4c6b4875 --- /dev/null +++ b/components/button/button-icon.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import withDefaults from '../utils/with-defaults' + +interface Props { + isRight?: boolean + className?: string +} + +const defaultProps = { + isRight: false, + className: '', +} + +type NativeAttrs = Omit, keyof Props> +export type ButtonIconProps = Props & typeof defaultProps & NativeAttrs + +const ButtonIcon: React.FC> = ({ + isRight, + children, + className, + ...props +}) => { + return ( + + {children} + + + ) +} + +const MemoButtonIcon = React.memo(ButtonIcon) + +export default withDefaults(MemoButtonIcon, defaultProps) diff --git a/components/button/button.tsx b/components/button/button.tsx index 31b54e99d..3817103e9 100644 --- a/components/button/button.tsx +++ b/components/button/button.tsx @@ -4,6 +4,7 @@ import useTheme from '../styles/use-theme' import { ButtonTypes, NormalSizes } from '../utils/prop-types' import ButtonDrip from './button.drip' import ButtonLoading from '../loading' +import ButtonIcon from './button-icon' import { getButtonColors, getButtonCursor, getButtonHoverColors, getButtonSize } from './styles' interface Props { @@ -15,6 +16,8 @@ interface Props { auto?: boolean effect?: boolean disabled?: boolean + icon?: React.ReactNode + iconRight?: React.ReactNode onClick?: React.MouseEventHandler className?: string } @@ -45,6 +48,8 @@ const Button: React.FC> = ({ onClick, auto, size, + icon, + iconRight, className, ...props }) => { @@ -94,6 +99,32 @@ const Button: React.FC> = ({ onClick && onClick(event) } + const childrenWithIcon = useMemo(() => { + const hasIcon = icon || iconRight + const isRight = Boolean(iconRight) + const paddingForAutoMode = + auto || size === 'mini' + ? `calc(var(--zeit-ui-button-height) / 2 + var(--zeit-ui-button-padding) * .5)` + : 0 + if (!hasIcon) return
{children}
+ return ( + <> + {hasIcon} +
+ {children} + +
+ + ) + }, [children, icon, auto, size]) + return (