-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
47 create tag component #55
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
35023f7
feat: adding tag component
deeved-hiuston-brisa d66dabd
Merge branch 'main' of github.com:iurynogueira/ion-react into 47-crea…
deeved-hiuston-brisa d7bbbc6
test: adding tests to tag component
deeved-hiuston-brisa 3ac8787
test: adding test custom color tag
Deeved d340f3a
test: removing debugs
Deeved 96a6dcc
style: improve style object
Deeved 51185a0
test: adding test icon component
Deeved abece6d
refactor: reduce complexity
deeved-hiuston-brisa b84a42f
refactor: improving code error-boundary component
deeved-hiuston-brisa 2c27b7e
test: improving tests
deeved-hiuston-brisa 6b572d5
docs: move stories to folder and improve examples
deeved-hiuston-brisa 04f4c0b
chore: merge branch 'main' into 47-create-tag-componenet
deeved-hiuston-brisa ecc14e8
refactor: improving code
deeved-hiuston-brisa 52083b8
fix: fix validateLabel function
deeved-hiuston-brisa ff8fe69
chore: merge branch 'main' into 47-create-tag-componenet
deeved-hiuston-brisa 7b6aa96
refactor: improving code
deeved-hiuston-brisa e0d7dd7
refactor: rename function
deeved-hiuston-brisa 1b08ba4
Merge branch 'main' into 47-create-tag-component
iurynogueira e671387
refactor: improving code
deeved-hiuston-brisa File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react'; | ||
|
||
import IonIcon from '../icons/icons'; | ||
import { ErrorBoundaryStyled } from './styled'; | ||
|
||
export interface ErrorBoundaryProps { | ||
msg: string; | ||
} | ||
const sizeIcon = 16; | ||
const iconType = 'info'; | ||
|
||
const ErrorBoundary = ({ msg }: ErrorBoundaryProps) => { | ||
return ( | ||
<ErrorBoundaryStyled data-testid="ion-error-boundary"> | ||
<IonIcon type={iconType} size={sizeIcon}></IonIcon> | ||
<div> | ||
<label>Error:</label> | ||
{msg} | ||
</div> | ||
</ErrorBoundaryStyled> | ||
); | ||
}; | ||
|
||
export default ErrorBoundary; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import stitches from '../../stitches.config'; | ||
|
||
const { styled } = stitches; | ||
|
||
export const ErrorBoundaryStyled = styled('div', { | ||
display: 'flex', | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
padding: '8px 16px 8px 12px', | ||
gap: 8, | ||
|
||
width: 'max-content', | ||
height: 24, | ||
|
||
backgroundColor: '$warning1', | ||
|
||
borderWidth: '1px 1px 1px 8px', | ||
borderStyle: 'solid', | ||
borderColor: '$warning7', | ||
borderRadius: '8px', | ||
|
||
fontSize: 14, | ||
color: '$neutral8', | ||
|
||
svg: { | ||
display: 'flex', | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
gap: 8, | ||
|
||
backgroundColor: '$warning7', | ||
fill: '$warning1', | ||
|
||
borderRadius: 8, | ||
}, | ||
|
||
div: { | ||
display: 'flex', | ||
gap: 4, | ||
}, | ||
|
||
label: { | ||
fontWeight: 'bold', | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export { default as Button } from './button'; | ||
export { default as Icon } from './icons'; | ||
export { default as IonChip } from './chip'; | ||
export { default as IonTag } from './tag'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './tag'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import stitches from '../../stitches.config'; | ||
|
||
const { styled } = stitches; | ||
|
||
const setColors = (bgColor: string, color: string) => ({ | ||
backgroundColor: bgColor, | ||
color: color, | ||
svg: { | ||
fill: color, | ||
}, | ||
}); | ||
|
||
export const TagStyle = styled('div', { | ||
display: 'flex', | ||
flexDirection: 'row', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
padding: '2px 8px', | ||
gap: '6px', | ||
|
||
width: 'max-content', | ||
height: 'max-content', | ||
minHeight: '20px', | ||
|
||
backgroundColor: '$whitetransparence90', | ||
color: '$neutral7', | ||
borderRadius: '50px', | ||
|
||
span: { | ||
fontSize: '12px', | ||
fontWeight: '400', | ||
lineHeight: '16px', | ||
}, | ||
|
||
variants: { | ||
status: { | ||
success: { | ||
...setColors('$positive1', '$positive7'), | ||
}, | ||
info: { | ||
...setColors('$info1', '$info7'), | ||
}, | ||
warning: { | ||
...setColors('$warning1', '$warning7'), | ||
}, | ||
negative: { | ||
...setColors('$negative1', '$negative7'), | ||
}, | ||
neutral: { | ||
...setColors('$neutral2', '$neutral7'), | ||
}, | ||
}, | ||
outline: { | ||
true: { | ||
border: '1px solid', | ||
}, | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
|
||
import IonTag, { IonTagProps } from './tag'; | ||
import { StatusType } from '../../core/types/status'; | ||
|
||
const defaultTag: IonTagProps = { | ||
label: 'tag label', | ||
}; | ||
|
||
const sut = (props = defaultTag) => render(<IonTag {...props} />); | ||
const tagId = 'ion-tag'; | ||
const getTag = () => screen.getByTestId(tagId); | ||
|
||
const customColor = '#AADD00'; | ||
|
||
describe('IonTag', () => { | ||
it('should render default tag ', () => { | ||
sut(); | ||
expect(getTag()).toBeTruthy(); | ||
}); | ||
|
||
it('should render tag with label "example tag"', async () => { | ||
const customLabel = 'example tag'; | ||
await sut({ label: customLabel }); | ||
expect(screen.findByText(customLabel)).toBeTruthy(); | ||
}); | ||
|
||
it.each([ | ||
'success', | ||
'info', | ||
'warning', | ||
'negative', | ||
'neutral', | ||
] as StatusType[])('should render tag with status: %s', (status) => { | ||
sut({ ...defaultTag, status: status }); | ||
expect(getTag().className).toContain(`status-${status}`); | ||
}); | ||
|
||
it('should not render outline in tag', async () => { | ||
await sut({ ...defaultTag, outline: false }); | ||
expect(getTag().className).not.toContain('outline-false'); | ||
}); | ||
|
||
it('should render outline in tag', async () => { | ||
await sut({ ...defaultTag, outline: true }); | ||
expect(getTag().className).toContain('outline-true'); | ||
}); | ||
|
||
it('should render tag with icon check', async () => { | ||
const iconType = 'check'; | ||
await sut({ ...defaultTag, icon: iconType }); | ||
const icon = screen.getByTestId(`ion-icon-${iconType}`); | ||
expect(icon).toBeTruthy(); | ||
}); | ||
|
||
it('should render ErrorBoundary component when not exist label', async () => { | ||
sut({ label: '' }); | ||
const msgError = 'Label cannot be empty'; | ||
const errorBoundary = screen.getByTestId('ion-error-boundary'); | ||
expect(errorBoundary).toBeTruthy(); | ||
expect(await screen.findByText(msgError)).toBeTruthy(); | ||
}); | ||
|
||
it('should render tag with custom color', async () => { | ||
await sut({ ...defaultTag, color: customColor }); | ||
expect(getTag().className).not.toContain('status'); | ||
}); | ||
|
||
it('should render the tag the same as it has a custom color', async () => { | ||
const statusInfo = 'status-info'; | ||
await sut({ ...defaultTag, status: 'info', color: customColor }); | ||
expect(getTag().className).toContain(statusInfo); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import React from 'react'; | ||
|
||
import { TagStyle } from './styles'; | ||
import IonIcon from '../icons/icons'; | ||
|
||
import { validateHexColor } from '../utils/validateHexColor'; | ||
import ErrorBoundary from '../error/error-boundary'; | ||
import { TagStatus } from '../../core/types/status'; | ||
import { iconType } from '../icons/svgs/icons'; | ||
|
||
export interface IonTagProps { | ||
outline?: boolean; | ||
status?: TagStatus; | ||
color?: string; | ||
label: string; | ||
icon?: iconType; | ||
} | ||
|
||
const iconSize = 12; | ||
const defaultColor = '#505566'; | ||
const lighteningFactor = '1A'; | ||
|
||
const isValidLabel = (label: string) => label && !(String(label).trim() === ''); | ||
|
||
const newColor = (color: string) => ({ | ||
backgroundColor: color + lighteningFactor, | ||
color: color, | ||
fill: color, | ||
}); | ||
|
||
const getColorObject = (status?: TagStatus, color?: string) => { | ||
if (status) { | ||
return {}; | ||
} | ||
|
||
if (!color || !validateHexColor(color)) { | ||
return { ...newColor(defaultColor) }; | ||
} | ||
|
||
return { | ||
...newColor(color), | ||
}; | ||
}; | ||
|
||
const IonTag = ({ | ||
label, | ||
color, | ||
icon, | ||
status, | ||
outline = true, | ||
}: IonTagProps) => { | ||
if (!isValidLabel(label)) { | ||
return <ErrorBoundary msg="Label cannot be empty" />; | ||
} | ||
|
||
return ( | ||
<TagStyle | ||
data-testid="ion-tag" | ||
status={status} | ||
outline={outline} | ||
css={{ ...getColorObject(status, color) }} | ||
> | ||
{icon && <IonIcon type={icon} size={iconSize} />} | ||
<span>{label}</span> | ||
</TagStyle> | ||
); | ||
}; | ||
|
||
export default IonTag; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const validateHexColor = (color: string): boolean => { | ||
return /^#(?:[0-9a-fA-F]{3,4}){1,2}$/.test(color); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export type StatusType = 'success' | 'info' | 'warning' | 'negative'; | ||
export type TagStatus = 'success' | 'info' | 'warning' | 'negative' | 'neutral'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { ComponentStory, ComponentMeta } from '@storybook/react'; | ||
|
||
import IonTag, { IonTagProps } from '../../components/tag/tag'; | ||
|
||
export default { | ||
title: 'Ion/Data Display/Tag', | ||
component: IonTag, | ||
} as ComponentMeta<typeof IonTag>; | ||
|
||
const Template: ComponentStory<typeof IonTag> = (args: IonTagProps) => ( | ||
<IonTag {...args} /> | ||
); | ||
|
||
export const tagDefault = Template.bind({}); | ||
tagDefault.storyName = 'type: default'; | ||
tagDefault.args = { | ||
label: 'Exemple Message', | ||
}; | ||
|
||
export const TagWithoutOutline = Template.bind({}); | ||
TagWithoutOutline.storyName = 'type: without outline'; | ||
TagWithoutOutline.args = { | ||
label: 'Exemple Message', | ||
outline: false, | ||
}; | ||
|
||
export const TagWithStatusSuccess = Template.bind({}); | ||
TagWithStatusSuccess.storyName = 'type: success'; | ||
TagWithStatusSuccess.args = { | ||
label: 'tag with status success', | ||
status: 'success', | ||
}; | ||
|
||
export const TagWithStatusWarning = Template.bind({}); | ||
TagWithStatusWarning.storyName = 'type: warning'; | ||
TagWithStatusWarning.args = { | ||
label: 'Exemple Message', | ||
status: 'warning', | ||
}; | ||
|
||
export const TagWithStatusInfo = Template.bind({}); | ||
TagWithStatusInfo.storyName = 'type: info'; | ||
TagWithStatusInfo.args = { | ||
label: 'Exemple Message', | ||
status: 'info', | ||
}; | ||
|
||
export const TagWithStatusNegative = Template.bind({}); | ||
TagWithStatusNegative.storyName = 'type: negative'; | ||
TagWithStatusNegative.args = { | ||
label: 'Exemple Message', | ||
status: 'negative', | ||
}; | ||
|
||
export const TagWithStatusNeutral = Template.bind({}); | ||
TagWithStatusNeutral.storyName = 'type: neutral'; | ||
TagWithStatusNeutral.args = { | ||
label: 'Exemple Message', | ||
status: 'neutral', | ||
}; | ||
|
||
export const TagCustomColor = Template.bind({}); | ||
TagCustomColor.storyName = 'type: custom'; | ||
TagCustomColor.args = { | ||
label: 'Exemple Message', | ||
color: '#7f0dff', | ||
}; | ||
|
||
export const tagWithIcon = Template.bind({}); | ||
tagWithIcon.storyName = 'type: with icon'; | ||
tagWithIcon.args = { | ||
label: 'Exemple Message', | ||
icon: 'check', | ||
status: 'success', | ||
outline: true, | ||
}; | ||
|
||
export const tagError = Template.bind({}); | ||
tagError.storyName = 'type: Error'; | ||
tagError.args = { | ||
label: '', | ||
icon: 'check', | ||
status: 'success', | ||
}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome component