diff --git a/src/stories/components/Tag.stories.tsx b/src/components/BoemlyTag/BoemlyTag.stories.tsx similarity index 65% rename from src/stories/components/Tag.stories.tsx rename to src/components/BoemlyTag/BoemlyTag.stories.tsx index bd5c2bc..6efcce3 100644 --- a/src/stories/components/Tag.stories.tsx +++ b/src/components/BoemlyTag/BoemlyTag.stories.tsx @@ -1,12 +1,11 @@ import React from 'react'; import { Meta, StoryFn } from '@storybook/react'; - -import { Tag } from '../..'; +import { BoemlyTag, BoemlyTagProps } from './BoemlyTag'; import { COLOR_SCHEMES } from '../../constants/colorSchemes'; export default { - title: 'Components/Tag', - component: Tag, + title: 'components/BoemlyTag', + component: BoemlyTag, argTypes: { variant: { options: ['solid', 'subtle', 'outline'], @@ -20,6 +19,13 @@ export default { options: COLOR_SCHEMES, control: { type: 'radio' }, }, + isClosable: { + options: [true, false], + control: { type: 'boolean' }, + }, + onClose: { + action: 'closed', + }, }, args: { children: 'Tag', @@ -27,21 +33,24 @@ export default { size: 'md', colorScheme: 'primary', }, -} as Meta; +} as Meta; -const Template: StoryFn = (args) => ; +const Template: StoryFn = (args) => ; export const Subtle = Template.bind({}); Subtle.args = { variant: 'subtle', + isClosable: true, }; export const Solid = Template.bind({}); Solid.args = { variant: 'solid', + isClosable: true, }; export const Outline = Template.bind({}); Outline.args = { variant: 'outline', + isClosable: true, }; diff --git a/src/components/BoemlyTag/BoemlyTag.test.tsx b/src/components/BoemlyTag/BoemlyTag.test.tsx new file mode 100644 index 0000000..a55730e --- /dev/null +++ b/src/components/BoemlyTag/BoemlyTag.test.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { screen, render, fireEvent } from '../../test/testUtils'; +import { BoemlyTag, BoemlyTagProps } from './BoemlyTag'; + +const defaultProps: BoemlyTagProps = { + children: 'Test Tag', + variant: 'solid', + colorScheme: 'blue', +}; + +const setup = (props: BoemlyTagProps = defaultProps) => { + render(); +}; + +describe('The BoemlyTag component', () => { + it('renders the tag without a close button if closable is false', () => { + setup({ ...defaultProps, isClosable: false }); + + expect(screen.getByText('Test Tag')).toBeInTheDocument(); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); + }); + + it('closes the tag when the close button is clicked', () => { + setup({ ...defaultProps, isClosable: true }); + + expect(screen.getByText('Test Tag')).toBeInTheDocument(); + + fireEvent.click(screen.getByRole('button')); + + expect(screen.queryByText('Test Tag')).not.toBeInTheDocument(); + }); +}); diff --git a/src/components/BoemlyTag/BoemlyTag.tsx b/src/components/BoemlyTag/BoemlyTag.tsx new file mode 100644 index 0000000..cebc23a --- /dev/null +++ b/src/components/BoemlyTag/BoemlyTag.tsx @@ -0,0 +1,32 @@ +import React, { useState } from 'react'; +import { Tag, TagCloseButton, TagLabel, TagProps } from '@chakra-ui/react'; + +export interface BoemlyTagProps extends TagProps { + isClosable?: boolean; + onClose?: () => void; +} + +export const BoemlyTag = ({ + isClosable = false, + onClose, + children, + ...props +}: BoemlyTagProps): JSX.Element => { + const [isVisible, setIsVisible] = useState(true); + + const handleClose = () => { + setIsVisible(false); + if (onClose) { + onClose(); + } + }; + + if (!isVisible) return <>; + + return ( + + {children} + {isClosable && } + + ); +}; diff --git a/src/components/BoemlyTag/index.ts b/src/components/BoemlyTag/index.ts new file mode 100644 index 0000000..38a20c6 --- /dev/null +++ b/src/components/BoemlyTag/index.ts @@ -0,0 +1 @@ +export { BoemlyTag } from './BoemlyTag'; diff --git a/src/index.tsx b/src/index.tsx index 4864bef..7105e65 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -35,6 +35,7 @@ export * from './components/BoemlyAlert'; export * from './components/BoemlyFormControl'; export * from './components/BoemlySteps'; export * from './components/BoemlyTabs'; +export * from './components/BoemlyTag'; export * from './components/BoemlyThemeProvider'; export * from './components/Wrapper'; export * from './components/ConfirmAction';