-
Notifications
You must be signed in to change notification settings - Fork 44
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
feat: add alert ds component #1781
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import type { FC } from 'react'; | ||
import styled, { FlattenSimpleInterpolation } from 'styled-components'; | ||
|
||
import type { TransformedHTMLAttributes } from '../Blocks.types'; | ||
import type { AlertVariant } from './Alert.types'; | ||
import { alertVariants } from './Alert.utils'; | ||
import { Cross } from 'blocks/icons'; | ||
import { HoverableSVG } from 'blocks/hoverableSVG'; | ||
import { getTextVariantStyles } from 'blocks/Blocks.utils'; | ||
|
||
export type AlertProps = { | ||
/* Additional prop from styled components to apply custom css to Alert */ | ||
css?: FlattenSimpleInterpolation; | ||
/* Sets the variant of the alert */ | ||
variant: AlertVariant; | ||
/* Close function to be called on close button click */ | ||
onClose?: () => void; | ||
/* Retry function to be called on action button click */ | ||
onAction?: () => void; | ||
/* Text to be displayed on the action button */ | ||
actionText?: string; | ||
/* Boolean to set the visibility of the icon */ | ||
showIcon?: boolean; | ||
/* Header text for the alert */ | ||
heading?: string; | ||
/* Description text for the alert */ | ||
description?: string; | ||
} & TransformedHTMLAttributes<HTMLDivElement>; | ||
|
||
const StyledAlert = styled.div<AlertProps>` | ||
/* Common Alert CSS */ | ||
|
||
display: flex; | ||
font-family: var(--font-family); | ||
border-radius: var(--radius-sm); | ||
justify-content: center; | ||
white-space: nowrap; | ||
padding: var(--spacing-xs); | ||
justify-content: space-between; | ||
${({ variant }) => ` | ||
border: var(--border-sm) solid var(--${alertVariants[variant].borderColor}); | ||
background-color: var(--${alertVariants[variant].bgColor}); | ||
`} | ||
|
||
/* Common icon css added through CSS class */ | ||
.icon { | ||
display: flex; | ||
justify-content: center; | ||
margin-right: var(--spacing-xxxs); | ||
color: var(--${({ variant }) => alertVariants[variant].iconColor}); | ||
} | ||
|
||
/* Custom CSS applied via styled component css prop */ | ||
${(props) => props.css || ''} | ||
`; | ||
|
||
const StyledLink = styled.div<{ variant: AlertVariant }>` | ||
/* Link CSS */ | ||
text-decoration: none; | ||
cursor: pointer; | ||
color: var(--${({ variant }) => alertVariants[variant].ctaColor}); | ||
`; | ||
|
||
const TextContainer = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
gap: var(--spacing-xxxs); | ||
flex: 1 0 0; | ||
`; | ||
|
||
const RightContainer = styled.div` | ||
display: flex; | ||
gap: var(--spacing-xs, 12px); | ||
align-items: center; | ||
height: 24px; | ||
`; | ||
|
||
const Heading = styled.p` | ||
${() => getTextVariantStyles('h5-semibold', 'components-alert-text-default')} | ||
`; | ||
|
||
const Description = styled.p` | ||
${() => getTextVariantStyles('bs-regular', 'components-alert-text-body')} | ||
`; | ||
|
||
const Alert: FC<AlertProps> = ({ | ||
description, | ||
heading, | ||
onClose, | ||
onAction, | ||
actionText = 'Try Again', | ||
showIcon = true, | ||
variant = 'info', | ||
...props | ||
}) => { | ||
const { icon: Icon } = alertVariants[variant]; | ||
|
||
return ( | ||
<StyledAlert | ||
role="alert" | ||
{...{ variant }} | ||
{...props} | ||
> | ||
{showIcon && ( | ||
<span className="icon"> | ||
<Icon size={24} /> | ||
</span> | ||
)} | ||
<TextContainer> | ||
{heading && <Heading>{heading}</Heading>} | ||
{description && <Description>{description}</Description>} | ||
</TextContainer> | ||
<RightContainer> | ||
{onAction && ( | ||
<StyledLink | ||
variant={variant} | ||
onClick={onAction} | ||
> | ||
{actionText} | ||
</StyledLink> | ||
)} | ||
{onClose && ( | ||
<HoverableSVG | ||
icon={ | ||
<Cross | ||
size={24} | ||
color="icon-primary" | ||
/> | ||
} | ||
onClick={onClose} | ||
/> | ||
)} | ||
</RightContainer> | ||
</StyledAlert> | ||
); | ||
}; | ||
|
||
Alert.displayName = 'Alert'; | ||
|
||
export { Alert }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type AlertVariant = 'success' | 'warning' | 'error' | 'info'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { AlertVariant } from './Alert.types'; | ||
import { IconProps, InfoFilled, TickCircleFilled, WarningCircleFilled } from '../icons'; | ||
import { ThemeColors } from 'blocks/theme/Theme.types'; | ||
import { FC } from 'react'; | ||
|
||
export const alertVariants: Record< | ||
AlertVariant, | ||
{ icon: FC<IconProps>; iconColor: ThemeColors; borderColor: ThemeColors; bgColor: ThemeColors; ctaColor: ThemeColors } | ||
> = { | ||
success: { | ||
icon: TickCircleFilled, | ||
iconColor: 'components-alert-icon-success', | ||
borderColor: 'components-alert-stroke-success', | ||
bgColor: 'components-alert-background-success', | ||
ctaColor: 'components-alert-text-cta-success', | ||
}, | ||
warning: { | ||
icon: WarningCircleFilled, | ||
iconColor: 'components-alert-icon-warning', | ||
borderColor: 'components-alert-stroke-warning', | ||
bgColor: 'components-alert-background-warning', | ||
ctaColor: 'components-alert-text-cta-warning', | ||
Comment on lines
+11
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check text area component for the color implementation for different variants. This constant isnt needed, it can be done in a much optimised way There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is similar to how we have implemented |
||
}, | ||
info: { | ||
icon: InfoFilled, | ||
iconColor: 'components-alert-icon-info', | ||
borderColor: 'components-alert-stroke-info', | ||
bgColor: 'components-alert-background-info', | ||
ctaColor: 'components-alert-text-cta-info', | ||
}, | ||
error: { | ||
icon: WarningCircleFilled, | ||
iconColor: 'components-alert-icon-error', | ||
borderColor: 'components-alert-stroke-error', | ||
bgColor: 'components-alert-background-error', | ||
ctaColor: 'components-alert-text-cta-error', | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './Alert'; | ||
export * from './Alert.utils'; | ||
export * from './Alert.types'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { colorBrands } from '../colors/colors.brands'; | ||
import { colorPrimitives } from '../colors/colors.primitives'; | ||
import { textSemantics } from './semantics.text'; | ||
|
||
export const alertSemantics = { | ||
'text-default': { light: textSemantics['primary'].light, dark: textSemantics['primary'].dark }, | ||
'text-body': { light: textSemantics['tertiary'].light, dark: textSemantics['tertiary'].dark }, | ||
'icon-success': { light: colorBrands['success-500'], dark: colorBrands['success-300'] }, | ||
'icon-warning': { light: colorBrands['warning-700'], dark: colorBrands['warning-100'] }, | ||
'icon-error': { light: colorBrands['danger-600'], dark: colorBrands['danger-500'] }, | ||
'icon-info': { light: colorPrimitives['blue-700'], dark: colorPrimitives['blue-100'] }, | ||
'text-cta-success': { light: colorBrands['success-500'], dark: colorBrands['success-300'] }, | ||
'text-cta-warning': { light: colorBrands['warning-700'], dark: colorBrands['warning-100'] }, | ||
'text-cta-error': { light: colorBrands['danger-600'], dark: colorBrands['danger-500'] }, | ||
'text-cta-info': { light: colorPrimitives['blue-700'], dark: colorPrimitives['blue-100'] }, | ||
'background-success': { light: colorBrands['success-100'], dark: colorBrands['success-900'] }, | ||
'background-warning': { light: colorBrands['warning-100'], dark: colorBrands['warning-900'] }, | ||
'background-error': { light: colorBrands['danger-100'], dark: colorBrands['danger-900'] }, | ||
'background-info': { light: colorPrimitives['blue-100'], dark: colorPrimitives['blue-900'] }, | ||
'stroke-success': { light: colorBrands['success-300'], dark: colorBrands['success-700'] }, | ||
'stroke-warning': { light: colorBrands['warning-300'], dark: colorBrands['warning-700'] }, | ||
'stroke-error': { light: colorBrands['danger-300'], dark: colorBrands['danger-700'] }, | ||
'stroke-info': { light: colorPrimitives['blue-300'], dark: colorPrimitives['blue-700'] }, | ||
}; |
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.
Add font sizes , weight, style and line height for the texts
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.
Please check the implementation of the
getTextVariantStyles
, it will appropriately add the required styles to the text.