-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react):
ImpactBadge
component (#1612)
* feat: added badge component * fix: removed unused variable * fix: comments * feat: export badge props to extends `ImpactBadge` interface * feat: added `ImpactBadge` component * fix: a11y tests * fix: comments
- Loading branch information
Showing
7 changed files
with
293 additions
and
2 deletions.
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,71 @@ | ||
--- | ||
title: ImpactBadge | ||
description: The ImpactBadge is an extension of the Badge component is designed to indicate the type of impact | ||
source: https://github.com/dequelabs/cauldron/tree/develop/packages/react/src/components/ImpactBadge/index.tsx | ||
--- | ||
|
||
import { ImpactBadge } from '@deque/cauldron-react'; | ||
|
||
```js | ||
import { ImpactBadge } from '@deque/cauldron-react'; | ||
``` | ||
|
||
## Example | ||
|
||
### Critical | ||
|
||
```jsx example | ||
<ImpactBadge type="critical" /> | ||
``` | ||
|
||
### Serious | ||
|
||
```jsx example | ||
<ImpactBadge type="serious" /> | ||
``` | ||
|
||
### Moderate | ||
|
||
```jsx example | ||
<ImpactBadge type="moderate" /> | ||
``` | ||
|
||
### Minor | ||
|
||
```jsx example | ||
<ImpactBadge type="minor" /> | ||
``` | ||
|
||
### Small size | ||
```jsx example | ||
<ImpactBadge type="minor" size="small" /> | ||
``` | ||
|
||
## Props | ||
|
||
### ImpactBadge | ||
|
||
<ComponentProps | ||
className={true} | ||
refType="HTMLDivElement" | ||
props={[ | ||
{ | ||
name: 'type', | ||
type: ['critical', 'serious', 'moderate', 'minor'], | ||
description: 'Variant of impact level', | ||
required: true | ||
}, | ||
{ | ||
name: 'size', | ||
type: ['default', 'small'], | ||
defaultValue: 'default', | ||
description: 'Visual style of the tag.' | ||
}, | ||
{ | ||
name: 'label', | ||
type: 'ContentNode', | ||
required: false, | ||
description: 'Label for the ImpactBadge element.' | ||
}, | ||
]} | ||
/> |
125 changes: 125 additions & 0 deletions
125
packages/react/src/components/ImpactBadge/index.test.tsx
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,125 @@ | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
import axe from '../../axe'; | ||
import ImpactBadge from './'; | ||
|
||
test('should render critical `ImpactBadge`', () => { | ||
render(<ImpactBadge type="critical" />); | ||
expect(screen.getByText(/critical/i)).toHaveClass( | ||
'ImpactBadge', | ||
'ImpactBadge--critical', | ||
'Badge' | ||
); | ||
}); | ||
|
||
test('should render correct icon for `critical` type', () => { | ||
render(<ImpactBadge type="critical" />); | ||
|
||
expect( | ||
screen.getByText(/critical/i).querySelector('.Icon.Icon--chevron-double-up') | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
test('should render serious `ImpactBadge`', () => { | ||
render(<ImpactBadge type="serious" />); | ||
expect(screen.getByText(/serious/i)).toHaveClass( | ||
'ImpactBadge', | ||
'ImpactBadge--serious', | ||
'Badge' | ||
); | ||
}); | ||
|
||
test('should render correct icon for `serious` type', () => { | ||
render(<ImpactBadge type="serious" />); | ||
|
||
expect( | ||
screen.getByText(/serious/i).querySelector('.Icon.Icon--chevron-up') | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
test('should render moderate `ImpactBadge`', () => { | ||
render(<ImpactBadge type="moderate" />); | ||
expect(screen.getByText(/moderate/i)).toHaveClass( | ||
'ImpactBadge', | ||
'ImpactBadge--moderate', | ||
'Badge' | ||
); | ||
}); | ||
|
||
test('should render correct icon for `moderate` type', () => { | ||
render(<ImpactBadge type="moderate" />); | ||
|
||
expect( | ||
screen.getByText(/moderate/i).querySelector('.Icon.Icon--chevron-down') | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
test('should render minor `ImpactBadge`', () => { | ||
render(<ImpactBadge type="minor" />); | ||
expect(screen.getByText(/minor/i)).toHaveClass( | ||
'ImpactBadge', | ||
'ImpactBadge--minor', | ||
'Badge' | ||
); | ||
}); | ||
|
||
test('should render correct icon for `minor` type', () => { | ||
render(<ImpactBadge type="minor" />); | ||
|
||
expect( | ||
screen.getByText(/minor/i).querySelector('.Icon.Icon--chevron-double-down') | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
test('passes classNames through', () => { | ||
render(<ImpactBadge type="critical" className="foo" />); | ||
expect(screen.getByText(/critical/i)).toHaveClass( | ||
'ImpactBadge', | ||
'ImpactBadge--critical', | ||
'Badge', | ||
'foo' | ||
); | ||
}); | ||
|
||
test('passes arbitrary props through', () => { | ||
render(<ImpactBadge type="critical" data-foo="true" />); | ||
expect(screen.getByText(/critical/i)).toHaveAttribute('data-foo', 'true'); | ||
}); | ||
|
||
test('should render small `ImpactBadge`', () => { | ||
render(<ImpactBadge type="critical" size="small" />); | ||
const SmallBadge = screen.getByText(/critical/i); | ||
expect(SmallBadge).toHaveClass('ImpactBadge', 'Badge--small'); | ||
}); | ||
|
||
test('should render custom label', () => { | ||
render(<ImpactBadge type="critical" label="custom label" />); | ||
const CustomLabel = screen.getByText(/custom label/i); | ||
expect(CustomLabel).toBeInTheDocument(); | ||
expect(screen.queryByText(/critical/i)).not.toBeInTheDocument(); | ||
}); | ||
|
||
test('should return no axe violations', async () => { | ||
const { container } = render( | ||
<> | ||
<ImpactBadge type="critical" /> | ||
<ImpactBadge type="serious" /> | ||
<ImpactBadge type="moderate" /> | ||
<ImpactBadge type="minor" /> | ||
|
||
<ImpactBadge type="critical" size="small" /> | ||
<ImpactBadge type="serious" size="small" /> | ||
<ImpactBadge type="moderate" size="small" /> | ||
<ImpactBadge type="minor" size="small" /> | ||
|
||
<ImpactBadge | ||
type="minor" | ||
size="small" | ||
label={'Custom Impact: Custom Minor'} | ||
/> | ||
</> | ||
); | ||
|
||
const results = await axe(container); | ||
expect(results).toHaveNoViolations(); | ||
}); |
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,53 @@ | ||
import React, { forwardRef } from 'react'; | ||
|
||
import Badge, { BadgeLabel } from '../Badge'; | ||
|
||
import { ContentNode } from '../../types'; | ||
import Icon, { IconType } from '../Icon'; | ||
import classNames from 'classnames'; | ||
|
||
type ImpactType = 'critical' | 'serious' | 'moderate' | 'minor'; | ||
|
||
interface ImpactBadgeProps | ||
extends Omit<React.ComponentProps<typeof Badge>, 'children'> { | ||
type: ImpactType; | ||
label?: ContentNode; | ||
} | ||
|
||
const iconByType: { [type in ImpactType]: IconType } = { | ||
critical: 'chevron-double-up', | ||
serious: 'chevron-up', | ||
moderate: 'chevron-down', | ||
minor: 'chevron-double-down' | ||
}; | ||
|
||
const typeValues: { [key in ImpactType]: string } = { | ||
critical: 'Critical', | ||
serious: 'Serious', | ||
moderate: 'Moderate', | ||
minor: 'Minor' | ||
}; | ||
|
||
const ImpactBadge = forwardRef<HTMLDivElement, ImpactBadgeProps>( | ||
({ type, label, className, ...other }, ref) => { | ||
return ( | ||
<Badge | ||
className={classNames(`ImpactBadge`, `ImpactBadge--${type}`, className)} | ||
ref={ref} | ||
{...other} | ||
> | ||
<Icon type={iconByType[type]} /> | ||
{label || ( | ||
<> | ||
<BadgeLabel>Impact:</BadgeLabel> | ||
{typeValues[type]} | ||
</> | ||
)} | ||
</Badge> | ||
); | ||
} | ||
); | ||
|
||
ImpactBadge.displayName = 'ImpactBadge'; | ||
|
||
export default ImpactBadge; |
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
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,39 @@ | ||
:root { | ||
--impact-badge-critical-background-color: var(--issue-critical); | ||
--impact-badge-critical-border-color: var(--accent-error-disabled); | ||
|
||
--impact-badge-serious-background-color: var(--issue-serious); | ||
--impact-badge-serious-border-color: var(--accent-warning); | ||
|
||
--impact-badge-moderate-background-color: var(--issue-moderate); | ||
--impact-badge-moderate-border-color: #eb94ff; | ||
|
||
--impact-badge-minor-background-color: var(--issue-minor); | ||
--impact-badge-minor-border-color: var(--gray-30); | ||
|
||
--impact-badge-text-color: var(--gray-90); | ||
} | ||
|
||
.ImpactBadge { | ||
--badge-text-color: var(--impact-badge-text-color); | ||
} | ||
|
||
.ImpactBadge--critical { | ||
--badge-background-color: var(--impact-badge-critical-background-color); | ||
--badge-border-color: var(--impact-badge-critical-border-color); | ||
} | ||
|
||
.ImpactBadge--serious { | ||
--badge-background-color: var(--impact-badge-serious-background-color); | ||
--badge-border-color: var(--impact-badge-serious-border-color); | ||
} | ||
|
||
.ImpactBadge--moderate { | ||
--badge-background-color: var(--impact-badge-moderate-background-color); | ||
--badge-border-color: var(--impact-badge-moderate-border-color); | ||
} | ||
|
||
.ImpactBadge--minor { | ||
--badge-background-color: var(--impact-badge-minor-background-color); | ||
--badge-border-color: var(--impact-badge-minor-border-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
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