-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #439 from AppQuality/UN-350-banner
feat: global alert
- Loading branch information
Showing
3 changed files
with
181 additions
and
0 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
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,35 @@ | ||
import { Meta as ComponentMeta, StoryFn as Story } from "@storybook/react"; | ||
import { | ||
GlobalAlert as UgGlobalAlert, | ||
GlobalAlertProps | ||
} from "."; | ||
import { Anchor } from "../../buttons/anchor"; | ||
|
||
const GlobalAlertTemplate: Story<GlobalAlertProps> = ({ ...props }) => ( | ||
<UgGlobalAlert {...props}> | ||
</UgGlobalAlert> | ||
); | ||
|
||
export const GlobalAlert = GlobalAlertTemplate.bind({}); | ||
GlobalAlert.args = { | ||
type: "info", | ||
title: "Account update", | ||
dismissable: true, | ||
onClose: () => {alert('dismissed')}, | ||
cta: "Find out more", | ||
message: <> | ||
Your account will automatically update in 5 days.{' '} | ||
<Anchor href="#" isExternal> | ||
Find out more | ||
</Anchor> | ||
</> | ||
}; | ||
|
||
export default { | ||
title: "Molecules/Notification", | ||
component: UgGlobalAlert, | ||
parameters: { | ||
// Sets a delay for the component's stories | ||
chromatic: { delay: 300 }, | ||
}, | ||
} as ComponentMeta<typeof UgGlobalAlert>; |
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,145 @@ | ||
import { | ||
GlobalAlert as ZendeskGlobalAlert, | ||
IGlobalAlertProps | ||
} from "@zendeskgarden/react-notifications"; | ||
import { forwardRef, ReactNode } from "react"; | ||
import styled from "styled-components"; | ||
import { getColor } from "../../theme/utils"; | ||
import { ButtonArgs } from "../../buttons/button/_types"; | ||
import { Button } from "../../buttons/button"; | ||
import { ReactComponent as AccentIcon } from "@zendeskgarden/svg-icons/src/16/lightbulb-stroke.svg"; | ||
import { ReactComponent as PrimaryIcon } from "@zendeskgarden/svg-icons/src/16/gear-stroke.svg"; | ||
|
||
export interface GlobalAlertProps extends Omit<IGlobalAlertProps, 'type'> { | ||
type: IGlobalAlertProps['type'] | "accent" | "primary"; | ||
message?: ReactNode; | ||
dismissable?: boolean; | ||
onClose?: () => void; | ||
cta?: string; | ||
} | ||
|
||
const StyledGlobalAlert = styled(ZendeskGlobalAlert) <GlobalAlertProps>` | ||
// general | ||
align-items: center; | ||
[data-garden-id="notifications.global-alert.icon"] { | ||
margin-top: -2px; | ||
} | ||
.global-alert-icon { | ||
flex-shrink: 0; | ||
margin-top: -2px; | ||
margin-right: 8px; | ||
width: 16px; | ||
height: 16px; | ||
} | ||
.global-alert-cta { | ||
flex-shrink: 0; | ||
} | ||
// looks like the following rules get overwritten by garden if we use props.type directly instead of alerttype | ||
// or even in file component.ts of the theme | ||
// Primary | ||
&[alerttype="primary"] { | ||
background-color: ${({ theme }) => getColor(theme.colors.primaryHue, 100)}; | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 700)}; | ||
box-shadow: 0 1px 1px ${({ theme }) => getColor(theme.colors.primaryHue, 300)}; | ||
[data-garden-id="notifications.global-alert.content"] { | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 700)}; | ||
} | ||
[data-garden-id="notifications.global-alert.title"] { | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 800)}; | ||
} | ||
[data-garden-id="buttons.anchor"] { | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 600)}; | ||
} | ||
.global-alert-icon { | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 700)}; | ||
} | ||
} | ||
// Accent | ||
&[alerttype="accent"] { | ||
background-color: ${({ theme }) => theme.palette.blue[100]}; | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 700)}; | ||
box-shadow: 0 1px 1px ${({ theme }) => getColor(theme.colors.accentHue, 600)}; | ||
[data-garden-id="notifications.global-alert.content"] { | ||
color: ${({ theme }) => getColor(theme.colors.accentHue, 700)}; | ||
} | ||
[data-garden-id="notifications.global-alert.title"] { | ||
color: ${({ theme }) => getColor(theme.colors.accentHue, 800)}; | ||
} | ||
[data-garden-id="buttons.anchor"] { | ||
color: ${({ theme }) => getColor(theme.colors.accentHue, 700)}; | ||
} | ||
.global-alert-icon { | ||
color: ${({ theme }) => getColor(theme.colors.accentHue, 700)}; | ||
} | ||
} | ||
// Info | ||
&[alerttype="info"] { | ||
background-color: ${({ theme }) => getColor(theme.colors.infoHue, 100)}; | ||
color: ${({ theme }) => getColor(theme.colors.primaryHue, 700)}; | ||
[data-garden-id="notifications.global-alert.content"] { | ||
color: ${({ theme }) => getColor(theme.colors.infoHue, 700)}; | ||
} | ||
[data-garden-id="notifications.global-alert.title"] { | ||
color: ${({ theme }) => getColor(theme.colors.infoHue, 800)}; | ||
} | ||
[data-garden-id="buttons.anchor"] { | ||
color: ${({ theme }) => getColor(theme.colors.infoHue, 700)}; | ||
} | ||
[data-garden-id="notifications.global-alert.icon"] { | ||
color: ${({ theme }) => getColor(theme.colors.infoHue, 700)}; | ||
} | ||
} | ||
// Error | ||
&[alerttype="error"] { | ||
.global-alert-cta { | ||
background-color: ${({ theme }) => getColor(theme.colors.dangerHue, 800)}; | ||
} | ||
} | ||
// Warning | ||
&[alerttype="warning"] { | ||
background-color: ${({ theme }) => getColor(theme.colors.warningHue, 300)}; | ||
box-shadow: 0 1px 1px ${({ theme }) => getColor(theme.colors.warningHue, 600)}; | ||
.global-alert-cta { | ||
background-color: ${({ theme }) => getColor(theme.colors.warningHue, 800)}; | ||
} | ||
} | ||
// Success | ||
&[alerttype="success"] { | ||
background-color: ${({ theme }) => getColor(theme.colors.successHue, 700)}; | ||
box-shadow: 0 1px 1px ${({ theme }) => getColor(theme.colors.successHue, 700)}; | ||
color: ${({ theme }) => getColor(theme.colors.successHue, 50)}; | ||
.global-alert-cta { | ||
background-color: ${({ theme }) => getColor(theme.colors.successHue, 800)}; | ||
} | ||
} | ||
`; | ||
|
||
const CustomButton = ({ isPill = true, isPrimary = true, ...props }: ButtonArgs) => ( | ||
<Button isPill={isPill} isPrimary={isPrimary} size="small" {...props} /> | ||
); | ||
|
||
export const GlobalAlert = forwardRef<HTMLDivElement, GlobalAlertProps>(({ type, onClose, dismissable, cta, title, message, ...props }, ref) => ( | ||
<StyledGlobalAlert ref={ref} type={type} {...props}> | ||
{type === "accent" && <AccentIcon className="global-alert-icon"/>} | ||
{type === "primary" && <PrimaryIcon className="global-alert-icon" />} | ||
<StyledGlobalAlert.Content> | ||
{title && <StyledGlobalAlert.Title>{title}</StyledGlobalAlert.Title>} | ||
{message} | ||
</StyledGlobalAlert.Content> | ||
{cta && <CustomButton className="global-alert-cta" isAccent={type==='accent'}>{cta}</CustomButton>} | ||
{dismissable && <StyledGlobalAlert.Close aria-label="Close Global Alert" onClick={onClose} />} | ||
</StyledGlobalAlert> | ||
)); | ||
|