Skip to content

Commit

Permalink
feat(store-ui): Add IconButton Molecule (#900)
Browse files Browse the repository at this point in the history
* Add IconButton molecule component

* Use IconButton on Carousel

* Fix stories and doc

* Fix default story and remove children from props

* Use css hover instead of tailwind hover

* Export IconButton

* Trigger CI

* Change story css

* Change Preview to Default

* Fix css

* Add css selectors on docs
  • Loading branch information
igorbrasileiro authored Aug 26, 2021
1 parent 6d76cec commit 0114409
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/store-ui/src/deprecated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export {
Container,
NavLink,
Message,
IconButton,
IconButton as UIIconButton,
MenuButton,
jsx,
useThemeUI,
Expand Down Expand Up @@ -70,7 +70,7 @@ export type {
ContainerProps,
NavLinkProps,
MessageProps,
IconButtonProps,
IconButtonProps as UIIconButtonProps,
MenuButtonProps,
} from 'theme-ui'

Expand Down
3 changes: 3 additions & 0 deletions packages/store-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export type { SearchInputProps } from './molecules/SearchInput'
export { default as Carousel } from './molecules/Carousel'
export type { CarouselProps } from './molecules/Carousel'

export { default as IconButton } from './molecules/IconButton'
export type { IconButtonProps } from './molecules/IconButton'

// Hooks
export { default as useSlider } from './hooks/useSlider'
export type {
Expand Down
17 changes: 7 additions & 10 deletions packages/store-ui/src/molecules/Carousel/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import type { PropsWithChildren } from 'react'
import React, { useMemo } from 'react'
import type { SwipeableProps } from 'react-swipeable'

import Button from '../../atoms/Button'
import Icon from '../../atoms/Icon'
import { RightArrowIcon, LeftArrowIcon } from './Arrows'
import useSlider from '../../hooks/useSlider/useSlider'
import useSlideVisibility from './hooks/useSlideVisibility'
import Bullets from '../Bullets'
import IconButton from '../IconButton'

const createTransformValues = (infinite: boolean, totalItems: number) => {
const transformMap: Record<number, number> = {}
Expand Down Expand Up @@ -155,7 +154,7 @@ function Carousel({

{showNavigationArrows && (
<div data-carousel-controls>
<Button
<IconButton
data-left-arrow
aria-controls={id}
aria-label="previous"
Expand All @@ -166,10 +165,9 @@ function Carousel({

slide('previous', sliderDispatch)
}}
>
<Icon component={<LeftArrowIcon />} />
</Button>
<Button
icon={<LeftArrowIcon />}
/>
<IconButton
data-right-arrow
aria-controls={id}
aria-label="next"
Expand All @@ -180,9 +178,8 @@ function Carousel({

slide('next', sliderDispatch)
}}
>
<Icon component={<RightArrowIcon />} />
</Button>
icon={<RightArrowIcon />}
/>
</div>
)}

Expand Down
27 changes: 27 additions & 0 deletions packages/store-ui/src/molecules/IconButton/IconButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react'
import { render } from '@testing-library/react'

import IconButton from './IconButton'

describe('IconButton', () => {
const testId = 'store-icon-button'

it('data-store-icon-button is present', () => {
const { getByTestId } = render(
<IconButton testId={testId} icon={<div>foo</div>} />
)

const iconButton = getByTestId(testId)

expect(iconButton).toBeInTheDocument()
expect(iconButton).toHaveAttribute('data-store-icon-button')
})

it('icon is present', () => {
const { getByTestId } = render(
<IconButton testId={testId} icon={<div data-testid="icon">foo</div>} />
)

expect(getByTestId('icon')).toBeInTheDocument()
})
})
30 changes: 30 additions & 0 deletions packages/store-ui/src/molecules/IconButton/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { ReactNode } from 'react'
import React, { forwardRef } from 'react'

import Button from '../../atoms/Button'
import type { ButtonProps } from '../../atoms/Button'
import Icon from '../../atoms/Icon'

export interface Props extends Omit<ButtonProps, 'children'> {
/**
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
*/
testId?: string
/**
* A React component that will be rendered as an icon.
*/
icon: ReactNode
}

const IconButton = forwardRef<HTMLButtonElement, Props>(function IconButton(
{ icon, testId = 'store-icon-button', ...buttonProps },
ref
) {
return (
<Button ref={ref} data-store-icon-button testId={testId} {...buttonProps}>
<Icon component={icon} />
</Button>
)
})

export default IconButton
2 changes: 2 additions & 0 deletions packages/store-ui/src/molecules/IconButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './IconButton'
export type { Props as IconButtonProps } from './IconButton'
25 changes: 25 additions & 0 deletions packages/store-ui/src/molecules/IconButton/stories/IconButton.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'
import IconButton from '../IconButton'

# Default

<Canvas>
<Story id="molecules-iconbutton--default" />
</Canvas>

# Custom Style

<Canvas>
<Story id="molecules-iconbutton--custom-style" />
</Canvas>

# Props

<ArgsTable of={IconButton} />

# CSS Selectors
```css
[data-store-icon-button] {}
```

This component inherits [Button](?path=/docs/atoms-button--button) component css selectors.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Story, Meta } from '@storybook/react'
import React from 'react'

import type { Props as IconButtonProps } from '../IconButton'
import Component from '../IconButton'
import ShoppingCartIcon from '../../../atoms/Icon/stories/assets/ShoppingCart'
import mdx from './IconButton.mdx'

const IconButtonTemplate: Story<IconButtonProps> = (props) => (
<Component {...props} icon={<ShoppingCartIcon />} />
)

export const Default = IconButtonTemplate.bind({})

const IconButtonCustomTemplate: Story<IconButtonProps> = (props) => {
return (
<Component {...props} className="iconButton" icon={<ShoppingCartIcon />} />
)
}

export const CustomStyle = IconButtonCustomTemplate.bind({})

export default {
title: 'Molecules/IconButton',
parameters: {
docs: {
page: mdx,
},
},
} as Meta
11 changes: 11 additions & 0 deletions themes/theme-b2c-tailwind/src/molecules/icon-button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[data-store-icon-button] {
@apply inline-flex;
}

.iconButton {
@apply text-black inline-flex bg-transparent cursor-pointer rounded-full p-2 transition-colors duration-150 ease-in;
}

.iconButton:hover {
@apply bg-gray-400 bg-opacity-40;
}
1 change: 1 addition & 0 deletions themes/theme-b2c-tailwind/src/molecules/index.css
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@import "./bullets.css";
@import "./search-input.css";
@import "./icon-button.css"

0 comments on commit 0114409

Please sign in to comment.