Skip to content

Commit 9589649

Browse files
authored
Merge pull request #784 from devtron-labs/feat/badge
feat: badge component
2 parents 6bcfbe6 + 28d5f0e commit 9589649

12 files changed

Lines changed: 150 additions & 28 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "1.15.3-pre-1",
3+
"version": "1.15.3-pre-2",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ComponentSizeType } from '@Shared/constants'
2+
3+
import { Icon } from '../Icon'
4+
import { BadgeProps } from './types'
5+
import { getClassNameAccToSize, getClassNameAccToVariant } from './utils'
6+
7+
const Badge = ({
8+
label,
9+
bgColor,
10+
fontColor,
11+
endIconProps,
12+
startIconProps,
13+
variant = 'default',
14+
size = ComponentSizeType.xs,
15+
}: BadgeProps) => {
16+
const { styles, iconColor } = getClassNameAccToVariant(variant)
17+
const iconSize = size === ComponentSizeType.xs ? 20 : 16
18+
19+
return (
20+
<div
21+
className={`flex dc__gap-4 br-4 fw-5 dc__w-fit-content ${getClassNameAccToSize(size)} ${styles}`}
22+
{...(bgColor && fontColor
23+
? {
24+
style: {
25+
backgroundColor: `var(--${bgColor})`,
26+
color: `var(--${fontColor})`,
27+
},
28+
}
29+
: {})}
30+
>
31+
{startIconProps && <Icon {...startIconProps} size={iconSize} color={fontColor || iconColor} />}
32+
<span className="dc__truncate">{label}</span>
33+
{endIconProps && <Icon {...endIconProps} size={iconSize} color={fontColor || iconColor} />}
34+
</div>
35+
)
36+
}
37+
38+
export default Badge
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as Badge } from './Badge'
2+
export type { BadgeProps } from './types'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ComponentSizeType } from '@Shared/constants'
2+
import { IconBaseColorType } from '@Shared/types'
3+
4+
import { IconsProps } from '../Icon'
5+
6+
export type BadgeVariants = 'default' | 'negative' | 'negative-grey' | 'positive' | 'warning' | 'neutral' | 'custom'
7+
8+
export type BadgeProps = {
9+
size?: Extract<ComponentSizeType, ComponentSizeType.xs | ComponentSizeType.xxs | ComponentSizeType.xxxs>
10+
startIconProps?: Omit<IconsProps, 'color' | 'size'>
11+
endIconProps?: Omit<IconsProps, 'color' | 'size'>
12+
label: string
13+
} & (
14+
| {
15+
variant?: Exclude<BadgeVariants, 'custom'>
16+
fontColor?: never
17+
bgColor?: never
18+
}
19+
| {
20+
variant: 'custom'
21+
fontColor: IconBaseColorType
22+
bgColor: IconBaseColorType
23+
}
24+
)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ComponentSizeType } from '@Shared/constants'
2+
import { IconBaseColorType } from '@Shared/types'
3+
4+
import { BadgeProps } from './types'
5+
6+
export const getClassNameAccToVariant = (
7+
variant: BadgeProps['variant'],
8+
): { styles: string; iconColor: IconBaseColorType } => {
9+
switch (variant) {
10+
case 'custom':
11+
return { styles: '', iconColor: 'B700' }
12+
case 'negative':
13+
return { styles: 'bcr-1 cr-7', iconColor: 'R700' }
14+
case 'warning':
15+
return { styles: 'bcy-50 cy-7', iconColor: 'Y700' }
16+
case 'positive':
17+
return { styles: 'bcg-1 cg-7', iconColor: 'G700' }
18+
case 'neutral':
19+
return { styles: 'bg__secondary cn-700', iconColor: 'N700' }
20+
case 'default':
21+
default:
22+
return { styles: 'bcb-1 cb-7', iconColor: 'B700' }
23+
}
24+
}
25+
26+
export const getClassNameAccToSize = (size: BadgeProps['size']) => {
27+
switch (size) {
28+
case ComponentSizeType.xxxs:
29+
return 'fs-11 lh-16 px-4 py-1'
30+
case ComponentSizeType.xxs:
31+
return 'fs-12 lh-16 px-6 py-2'
32+
case ComponentSizeType.xs:
33+
default:
34+
return 'fs-13 lh-20 px-6 py-2'
35+
}
36+
}

src/Shared/Components/Button/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ButtonProps } from './types'
2121

2222
export const BUTTON_SIZE_TO_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
2323
[ComponentSizeType.xxs_small_icon]: `${COMPONENT_SIZE_TYPE_TO_FONT_AND_BLOCK_PADDING_MAP[ComponentSizeType.xxs]} px-9 dc__gap-6 mw-48`,
24+
[ComponentSizeType.xxxs]: `${COMPONENT_SIZE_TYPE_TO_FONT_AND_BLOCK_PADDING_MAP[ComponentSizeType.xxs]} px-9 dc__gap-6 mw-48`,
2425
[ComponentSizeType.xxs]: `${COMPONENT_SIZE_TYPE_TO_FONT_AND_BLOCK_PADDING_MAP[ComponentSizeType.xxs]} px-9 dc__gap-6 mw-48`,
2526
[ComponentSizeType.xs]: `${COMPONENT_SIZE_TYPE_TO_FONT_AND_BLOCK_PADDING_MAP[ComponentSizeType.xs]} px-9 dc__gap-6 mw-48`,
2627
[ComponentSizeType.small]: `${COMPONENT_SIZE_TYPE_TO_FONT_AND_BLOCK_PADDING_MAP[ComponentSizeType.small]} px-9 dc__gap-8 mw-48`,
@@ -36,6 +37,7 @@ export const BUTTON_FONT_WEIGHT_TO_CLASS_NAME_MAP: Record<ButtonProps['fontWeigh
3637

3738
export const ICON_BUTTON_SIZE_TO_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
3839
[ComponentSizeType.xxs_small_icon]: 'p-4',
40+
[ComponentSizeType.xxxs]: 'p-1',
3941
[ComponentSizeType.xxs]: 'p-1',
4042
[ComponentSizeType.xs]: 'p-3',
4143
[ComponentSizeType.small]: 'p-5',
@@ -46,6 +48,7 @@ export const ICON_BUTTON_SIZE_TO_CLASS_NAME_MAP: Record<ButtonProps['size'], str
4648

4749
export const BUTTON_SIZE_TO_ICON_SIZE_MAP: Record<ButtonProps['size'], ProgressingProps['size']> = {
4850
[ComponentSizeType.xxs_small_icon]: 12,
51+
[ComponentSizeType.xxxs]: 14,
4952
[ComponentSizeType.xxs]: 14,
5053
[ComponentSizeType.xs]: 14,
5154
[ComponentSizeType.small]: 16,
@@ -56,6 +59,7 @@ export const BUTTON_SIZE_TO_ICON_SIZE_MAP: Record<ButtonProps['size'], Progressi
5659

5760
export const ICON_BUTTON_SIZE_TO_ICON_SIZE_MAP: Record<ButtonProps['size'], ProgressingProps['size']> = {
5861
[ComponentSizeType.xxs_small_icon]: 12,
62+
[ComponentSizeType.xxxs]: 16,
5963
[ComponentSizeType.xxs]: 16,
6064
[ComponentSizeType.xs]: 16,
6165
[ComponentSizeType.small]: 16,

src/Shared/Components/Security/SecurityModal/config/CodeScan.tsx

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import SeverityChip from '../../SeverityChip'
1718
import { getCVEUrlFromCVEName } from '../../utils'
1819
import { OpenDetailViewButton } from '../components'
1920
import IndexedTextDisplay from '../components/IndexedTextDisplay'
@@ -29,6 +30,7 @@ import {
2930
OpenDetailViewButtonProps,
3031
ScanResultDTO,
3132
SecurityModalStateType,
33+
SeveritiesDTO,
3234
StatusType,
3335
SUB_CATEGORIES,
3436
TablePropsType,
@@ -77,11 +79,7 @@ export const getCodeScanVulnerabilities = (data: CodeScan['vulnerability'], hide
7779
cellContent: element.cveId,
7880
},
7981
{
80-
component: (
81-
<span className={`severity-chip severity-chip--${element.severity?.toLowerCase()}`}>
82-
{element.severity}
83-
</span>
84-
),
82+
component: <SeverityChip severity={element.severity} />,
8583
cellContent: element.severity,
8684
},
8785
{
@@ -137,11 +135,7 @@ export const getCodeScanLicense = (data: CodeScan['license']) => ({
137135
cellContent: element.classification,
138136
},
139137
{
140-
component: (
141-
<span className={`severity-chip severity-chip--${element.severity?.toLowerCase()}`}>
142-
{element.severity}
143-
</span>
144-
),
138+
component: <SeverityChip severity={element.severity as SeveritiesDTO} />,
145139
cellContent: element.severity,
146140
},
147141
{
@@ -214,11 +208,7 @@ const getMisconfigurationsDetail = (
214208
cellContent: '',
215209
},
216210
{
217-
component: (
218-
<span className={`severity-chip severity-chip--${child.severity?.toLowerCase()}`}>
219-
{child.severity}
220-
</span>
221-
),
211+
component: <SeverityChip severity={child.severity as SeveritiesDTO} />,
222212
cellContent: child.severity,
223213
},
224214
{
@@ -332,11 +322,7 @@ const getExposedSecretsDetail = (
332322
cellContent: '',
333323
},
334324
{
335-
component: (
336-
<span className={`severity-chip severity-chip--${child.severity?.toLowerCase()}`}>
337-
{child.severity}
338-
</span>
339-
),
325+
component: <SeverityChip severity={child.severity as SeveritiesDTO} />,
340326
cellContent: child.severity,
341327
},
342328
{

src/Shared/Components/Security/SecurityModal/config/ImageScan.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ReactComponent as ICSuccess } from '@Icons/ic-success.svg'
2121
import { Progressing } from '@Common/Progressing'
2222

2323
import { DATE_TIME_FORMATS, ZERO_TIME_STRING } from '../../../../../Common/Constants'
24+
import SeverityChip from '../../SeverityChip'
2425
import { OpenDetailViewButton } from '../components'
2526
import { SCAN_FAILED_EMPTY_STATE, SCAN_IN_PROGRESS_EMPTY_STATE, SEVERITY_DEFAULT_SORT_ORDER } from '../constants'
2627
import {
@@ -34,6 +35,7 @@ import {
3435
OpenDetailViewButtonProps,
3536
ScanResultDTO,
3637
SecurityModalStateType,
38+
SeveritiesDTO,
3739
StatusType,
3840
SUB_CATEGORIES,
3941
TablePropsType,
@@ -232,11 +234,7 @@ const getLicenseDetailData = (element: ImageScanLicenseListType) => ({
232234
cellContent: child.classification,
233235
},
234236
{
235-
component: (
236-
<span className={`severity-chip severity-chip--${child.severity?.toLowerCase()}`}>
237-
{child.severity}
238-
</span>
239-
),
237+
component: <SeverityChip severity={child.severity as SeveritiesDTO} />,
240238
cellContent: child.severity,
241239
},
242240
{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { capitalizeFirstLetter } from '@Common/Helper'
2+
import { ComponentSizeType } from '@Shared/constants'
3+
4+
import { Badge, BadgeProps } from '../Badge'
5+
import { SeveritiesDTO } from './SecurityModal'
6+
7+
const SeverityChip = ({ severity, count }: { severity: SeveritiesDTO; count?: number }) => {
8+
const label = count ? `${count} ${capitalizeFirstLetter(severity)}` : capitalizeFirstLetter(severity)
9+
const commonProps: Pick<BadgeProps, 'size' | 'label'> = {
10+
size: ComponentSizeType.xxs,
11+
label,
12+
}
13+
switch (severity) {
14+
case SeveritiesDTO.CRITICAL:
15+
return <Badge {...commonProps} variant="negative" />
16+
case SeveritiesDTO.HIGH:
17+
return <Badge {...commonProps} variant="custom" fontColor="R500" bgColor="R100" />
18+
case SeveritiesDTO.MEDIUM:
19+
return <Badge {...commonProps} variant="custom" fontColor="O600" bgColor="O100" />
20+
case SeveritiesDTO.LOW:
21+
return <Badge {...commonProps} variant="warning" />
22+
case SeveritiesDTO.UNKNOWN:
23+
return <Badge {...commonProps} variant="neutral" />
24+
default:
25+
return <Badge {...commonProps} />
26+
}
27+
}
28+
29+
export default SeverityChip

0 commit comments

Comments
 (0)