Skip to content

Commit

Permalink
Merge pull request #179 from unix/button
Browse files Browse the repository at this point in the history
feat(button): support to display icons in button
  • Loading branch information
unix authored May 7, 2020
2 parents ee50d8d + 080ed93 commit 455e8d7
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 30 deletions.
189 changes: 189 additions & 0 deletions components/button/__tests__/__snapshots__/icon.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ButtonIcon should render correctly 1`] = `
"<button class=\\"btn \\"><span class=\\"icon \\"><svg></svg><style>
.icon {
position: absolute;
left: var(--zeit-ui-button-padding);
right: auto;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: center;
align-items: center;
color: var(--zeit-ui-button-color);
z-index: 1;
}
.right {
right: var(--zeit-ui-button-padding);
left: auto;
}
.icon :global(svg) {
background: transparent;
height: calc(var(--zeit-ui-button-height) / 2.35);
width: calc(var(--zeit-ui-button-height) / 2.35);
}
</style></span><div class=\\"text left\\">action<style>
.left {
padding-left: 0;
}
.right {
padding-right: 0;
}
</style></div><style>
.btn {
box-sizing: border-box;
display: inline-block;
padding: 0 1.375rem;
height: 2.5rem;
line-height: 2.5rem;
min-width: 12.5rem;
width: auto;
border-radius: 5px;
font-weight: 400;
font-size: .875rem;
user-select: none;
outline: none;
text-transform: capitalize;
justify-content: center;
text-align: center;
white-space: nowrap;
transition: all 0.2s ease 0s;
position: relative;
overflow: hidden;
color: #666;
background-color: #fff;
border: 1px solid #eaeaea;
cursor: pointer;
pointer-events: auto;
box-shadow: none;
--zeit-ui-button-padding: 1.375rem;
--zeit-ui-button-height: 2.5rem;
--zeit-ui-button-color: #666;
}
.btn:hover {
color: #000;
--zeit-ui-button-color: #000;
background-color: #fff;
border-color: #000;
cursor: pointer;
pointer-events: auto;
box-shadow: none;
transform: translate3d(0px, 0px, 0px);
}
.btn :global(.text) {
position: relative;
z-index: 1;
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
line-height: inherit;
top: -1px;
}
.btn :global(.text p),
.btn :global(.text pre),
.btn :global(.text div) {
margin: 0;
}
</style></button>"
`;
exports[`ButtonIcon should work with right 1`] = `
"<button class=\\"btn \\"><span class=\\"icon right \\"><svg></svg><style>
.icon {
position: absolute;
left: var(--zeit-ui-button-padding);
right: auto;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: center;
align-items: center;
color: var(--zeit-ui-button-color);
z-index: 1;
}
.right {
right: var(--zeit-ui-button-padding);
left: auto;
}
.icon :global(svg) {
background: transparent;
height: calc(var(--zeit-ui-button-height) / 2.35);
width: calc(var(--zeit-ui-button-height) / 2.35);
}
</style></span><div class=\\"text right\\">action<style>
.left {
padding-left: 0;
}
.right {
padding-right: 0;
}
</style></div><style>
.btn {
box-sizing: border-box;
display: inline-block;
padding: 0 1.375rem;
height: 2.5rem;
line-height: 2.5rem;
min-width: 12.5rem;
width: auto;
border-radius: 5px;
font-weight: 400;
font-size: .875rem;
user-select: none;
outline: none;
text-transform: capitalize;
justify-content: center;
text-align: center;
white-space: nowrap;
transition: all 0.2s ease 0s;
position: relative;
overflow: hidden;
color: #666;
background-color: #fff;
border: 1px solid #eaeaea;
cursor: pointer;
pointer-events: auto;
box-shadow: none;
--zeit-ui-button-padding: 1.375rem;
--zeit-ui-button-height: 2.5rem;
--zeit-ui-button-color: #666;
}
.btn:hover {
color: #000;
--zeit-ui-button-color: #000;
background-color: #fff;
border-color: #000;
cursor: pointer;
pointer-events: auto;
box-shadow: none;
transform: translate3d(0px, 0px, 0px);
}
.btn :global(.text) {
position: relative;
z-index: 1;
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
line-height: inherit;
top: -1px;
}
.btn :global(.text p),
.btn :global(.text pre),
.btn :global(.text div) {
margin: 0;
}
</style></button>"
`;
41 changes: 41 additions & 0 deletions components/button/__tests__/icon.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react'
import { mount } from 'enzyme'
import { Button } from 'components'
const Icon: React.FC<any> = () => <svg />

describe('ButtonIcon', () => {
it('should render correctly', () => {
const wrapper = mount(<Button icon={<Icon />}>action</Button>)
expect(wrapper.html()).toMatchSnapshot()
expect(() => wrapper.unmount()).not.toThrow()
})

it('should work with right', () => {
const wrapper = mount(<Button iconRight={<Icon />}>action</Button>)
expect(wrapper.html()).toMatchSnapshot()
expect(() => wrapper.unmount()).not.toThrow()
})

it('the width of the text should be filled', () => {
const autoWrapper = mount(
<Button auto icon={<Icon />}>
action
</Button>,
)
const wrapper = mount(<Button icon={<Icon />}>action</Button>)

const autoHtml = autoWrapper.find('.text').html()
const html = wrapper.find('.text').html()
expect(html).not.toEqual(autoHtml)

const mini = mount(<Button size="mini">action</Button>)
const miniIcon = mount(
<Button size="mini" icon={<Icon />}>
action
</Button>,
)
const miniHtml = mini.find('.text').html()
const miniIconHtml = miniIcon.find('.text').html()
expect(miniHtml).not.toEqual(miniIconHtml)
})
})
2 changes: 1 addition & 1 deletion components/button/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down
57 changes: 57 additions & 0 deletions components/button/button-icon.tsx
Original file line number Diff line number Diff line change
@@ -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<React.HTMLAttributes<any>, keyof Props>
export type ButtonIconProps = Props & typeof defaultProps & NativeAttrs

const ButtonIcon: React.FC<React.PropsWithChildren<ButtonIconProps>> = ({
isRight,
children,
className,
...props
}) => {
return (
<span className={`icon ${isRight ? 'right' : ''} ${className}`} {...props}>
{children}
<style jsx>{`
.icon {
position: absolute;
left: var(--zeit-ui-button-padding);
right: auto;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: center;
align-items: center;
color: var(--zeit-ui-button-color);
z-index: 1;
}
.right {
right: var(--zeit-ui-button-padding);
left: auto;
}
.icon :global(svg) {
background: transparent;
height: calc(var(--zeit-ui-button-height) / 2.35);
width: calc(var(--zeit-ui-button-height) / 2.35);
}
`}</style>
</span>
)
}

const MemoButtonIcon = React.memo(ButtonIcon)

export default withDefaults(MemoButtonIcon, defaultProps)
Loading

0 comments on commit 455e8d7

Please sign in to comment.