diff --git a/README.md b/README.md index 494e19d..ce85e19 100644 --- a/README.md +++ b/README.md @@ -118,3 +118,4 @@ function App() { - [Button](https://github.com/wri/wri-design-systems/tree/main/src/components/Buttons/Button) - [CloseButton](https://github.com/wri/wri-design-systems/tree/main/src/components/Buttons/CloseButton) +- [IconButton](https://github.com/wri/wri-design-systems/tree/main/src/components/Buttons/IconButton) diff --git a/src/components/Buttons/Button/index.tsx b/src/components/Buttons/Button/index.tsx index 64ee9f5..8ac68ef 100644 --- a/src/components/Buttons/Button/index.tsx +++ b/src/components/Buttons/Button/index.tsx @@ -57,7 +57,7 @@ const Button = ({ ) : null} {label} {rightIcon && !loading ? ( - + {rightIcon} ) : null} diff --git a/src/components/Buttons/CloseButton/Button.stories.tsx b/src/components/Buttons/CloseButton/CloseButton.stories.tsx similarity index 100% rename from src/components/Buttons/CloseButton/Button.stories.tsx rename to src/components/Buttons/CloseButton/CloseButton.stories.tsx diff --git a/src/components/Buttons/CloseButton/index.tsx b/src/components/Buttons/CloseButton/index.tsx index 08ae087..688fb7c 100644 --- a/src/components/Buttons/CloseButton/index.tsx +++ b/src/components/Buttons/CloseButton/index.tsx @@ -7,12 +7,11 @@ import { CloseIcon } from '../../icons' const CloseButton = ({ disabled, ...rest }: CloseButtonProps) => ( } aria-label={rest['aria-label'] || 'Close'} disabled={disabled} {...rest} - > - - + /> ) export default CloseButton diff --git a/src/components/Buttons/CloseButton/styled.ts b/src/components/Buttons/CloseButton/styled.ts index 5985f71..637602e 100644 --- a/src/components/Buttons/CloseButton/styled.ts +++ b/src/components/Buttons/CloseButton/styled.ts @@ -1,8 +1,8 @@ import styled from '@emotion/styled' -import { Button } from '@chakra-ui/react' import { getThemedColor } from '../../../lib/theme' +import IconButton from '../IconButton' -export const StyledCloseButton = styled(Button)` +export const StyledCloseButton = styled(IconButton)` width: 20px !important; padding: 0 !important; min-width: 20px !important; @@ -20,6 +20,7 @@ export const StyledCloseButton = styled(Button)` } &:hover { + background-color: ${getThemedColor('neutral', 300)}; box-shadow: 0px 1px 2px -1px #0000001a; box-shadow: 0px 1px 3px 0px #0000001a; } diff --git a/src/components/Buttons/IconButton/IconButton.stories.tsx b/src/components/Buttons/IconButton/IconButton.stories.tsx new file mode 100644 index 0000000..1cdf380 --- /dev/null +++ b/src/components/Buttons/IconButton/IconButton.stories.tsx @@ -0,0 +1,33 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import React from 'react' + +import type { Meta, StoryObj } from '@storybook/react' +import { fn } from '@storybook/test' +import IconButton from '.' +import { CheckIcon, MenuDotsIcon } from '../../icons' + +const meta = { + title: 'Buttons/Icon Button', + component: IconButton, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + args: { onClick: fn() }, +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + icon: , + }, +} + +export const Disabled: Story = { + args: { + icon: , + disabled: true, + }, +} diff --git a/src/components/Buttons/IconButton/IconButtonDemo.tsx b/src/components/Buttons/IconButton/IconButtonDemo.tsx new file mode 100644 index 0000000..bd6a4a2 --- /dev/null +++ b/src/components/Buttons/IconButton/IconButtonDemo.tsx @@ -0,0 +1,12 @@ +import { IconButton } from '../..' +import { CheckIcon, InfoIcon, MenuDotsIcon } from '../../icons' + +const IconButtonDemo = () => ( +
+ } aria-label='Menu' /> + } aria-label='Check' /> + } aria-label='Info' disabled /> +
+) + +export default IconButtonDemo diff --git a/src/components/Buttons/IconButton/README.md b/src/components/Buttons/IconButton/README.md new file mode 100644 index 0000000..d367084 --- /dev/null +++ b/src/components/Buttons/IconButton/README.md @@ -0,0 +1,51 @@ +# IconButton + +[Storybook Ref](https://wri.github.io/wri-design-systems/?path=/docs/buttons-icon-button--docs) + +[IconButton](https://github.com/wri/wri-design-systems/blob/main/src/components/Buttons/IconButton/IconButtonDemo.tsx) + +## Import + +```js +import { IconButton } from 'wri-design-systems' +``` + +## Usage + +```html +} + aria-label='Menu' +/> +``` + +## Props + +```ts +type IconButtonProps = Omit< + ChakraButtonProps, + 'size' | 'variant' | 'colorPalette' | 'children' | '_loading' +> & { + icon: React.ReactNode + disabled?: boolean +} +``` + +## Default + +```html +} + aria-label='Menu' +/> +``` + +## Disabled + +```html +} + aria-label='Info' + disabled +/> +``` diff --git a/src/components/Buttons/IconButton/index.tsx b/src/components/Buttons/IconButton/index.tsx new file mode 100644 index 0000000..5c14656 --- /dev/null +++ b/src/components/Buttons/IconButton/index.tsx @@ -0,0 +1,17 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import React from 'react' + +import { StyledIconButton } from './styled' +import { IconButtonProps } from './types' + +const IconButton = ({ icon, disabled, ...rest }: IconButtonProps) => ( + + {icon} + +) + +export default IconButton diff --git a/src/components/Buttons/IconButton/styled.ts b/src/components/Buttons/IconButton/styled.ts new file mode 100644 index 0000000..d81a1b5 --- /dev/null +++ b/src/components/Buttons/IconButton/styled.ts @@ -0,0 +1,51 @@ +import styled from '@emotion/styled' +import { Button } from '@chakra-ui/react' +import { getThemedColor } from '../../../lib/theme' + +export const StyledIconButton = styled(Button)` + width: 20px !important; + padding: 0 !important; + min-width: 20px !important; + height: 20px; + border-radius: 2px; + background-color: transparent; + + svg { + width: 15px; + height: 15px; + + path { + fill: ${getThemedColor('neutral', 800)}; + } + } + + &:hover { + background-color: color-mix( + in srgb, + ${getThemedColor('primary', 500)} 20%, + transparent + ); + } + + &:active { + background-color: color-mix( + in srgb, + ${getThemedColor('primary', 500)} 40%, + transparent + ); + } + + &:focus-visible { + outline-color: ${getThemedColor('primary', 700)}; + } + + &:disabled { + background-color: transparent; + + svg { + path { + fill: ${getThemedColor('neutral', 500)}; + } + } + } +` diff --git a/src/components/Buttons/IconButton/types.ts b/src/components/Buttons/IconButton/types.ts new file mode 100644 index 0000000..d732d3a --- /dev/null +++ b/src/components/Buttons/IconButton/types.ts @@ -0,0 +1,10 @@ +import React from 'react' +import { ButtonProps as ChakraButtonProps } from '@chakra-ui/react' + +export type IconButtonProps = Omit< + ChakraButtonProps, + 'size' | 'variant' | 'colorPalette' | 'children' | '_loading' +> & { + icon: React.ReactNode + disabled?: boolean +} diff --git a/src/components/icons/MenuDots.tsx b/src/components/icons/MenuDots.tsx new file mode 100644 index 0000000..c950cce --- /dev/null +++ b/src/components/icons/MenuDots.tsx @@ -0,0 +1,21 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import React from 'react' + +import { Icon, IconProps } from '@chakra-ui/react' + +export const MenuDotsIcon = (props: IconProps) => ( + + + + + +) diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index c15b6a1..fe8f57a 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -5,3 +5,4 @@ export * from './CheckIndeterminate' export * from './Info' export * from './ChevronDown' export * from './Close' +export * from './MenuDots' diff --git a/src/components/index.ts b/src/components/index.ts index e4066de..e800af5 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -14,3 +14,4 @@ export { default as Banner } from './Banner' export { default as Input } from './Input' export { default as Textarea } from './Textarea' export { default as CloseButton } from './Buttons/CloseButton' +export { default as IconButton } from './Buttons/IconButton'