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(}>action)
+ expect(wrapper.html()).toMatchSnapshot()
+ expect(() => wrapper.unmount()).not.toThrow()
+ })
+
+ it('should work with right', () => {
+ const wrapper = mount(}>action)
+ expect(wrapper.html()).toMatchSnapshot()
+ expect(() => wrapper.unmount()).not.toThrow()
+ })
+
+ it('the width of the text should be filled', () => {
+ const autoWrapper = mount(
+ }>
+ action
+ ,
+ )
+ const wrapper = mount(}>action)
+
+ const autoHtml = autoWrapper.find('.text').html()
+ const html = wrapper.find('.text').html()
+ expect(html).not.toEqual(autoHtml)
+
+ const mini = mount()
+ const miniIcon = mount(
+ }>
+ action
+ ,
+ )
+ 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 (