Skip to content

Commit

Permalink
chore: [M3-6080] - Add a ProductInformationBanner to all product land…
Browse files Browse the repository at this point in the history
…ing pages (#9523)

* Add banner to all product landing pages

* Add banners for Longview and LinodeCreate (Marketplace)

* Added changeset: Add Product Information Banners for all product landing pages

* Fix linting warnings for import order

* Add banner to product empty state landing pages

* Add banner to product create and detail pages

* WIP - dynamically style banner

* Add variant prop to Notice and update all Notices

* Fix linting warnings for prop order after renaming prop

* Fix inconsistency with important prop assignment

* Address feedback: place ProductInfoBanners with routing

* Fix one Notice with an incorrect variant prop
  • Loading branch information
mjac0bs authored Aug 25, 2023
1 parent 0af88ff commit e88b324
Show file tree
Hide file tree
Showing 215 changed files with 682 additions and 471 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tech Stories
---

Add Product Information Banners for all product landing pages ([#9523](https://github.com/linode/manager/pull/9523))
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const AbuseTicketBanner = () => {
}}
important
preferenceKey={preferenceKey}
warning
variant="warning"
>
<Typography>
{message}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const AccessPanel = (props: Props) => {
className
)}
>
{error ? <Notice error text={error} /> : null}
{error ? <Notice text={error} variant="error" /> : null}
<React.Suspense fallback={<SuspenseLoader />}>
<PasswordInput
autoComplete="off"
Expand Down
6 changes: 3 additions & 3 deletions packages/manager/src/components/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ export const Accordion = (props: AccordionProps) => {
<Notice
data-qa-notice
text={notice}
{...(success && { success: true })}
{...(warning && { warning: true })}
{...(error && { error: true })}
{...(success && { variant: 'success' })}
{...(warning && { variant: 'warning' })}
{...(error && { variant: 'error' })}
spacingBottom={0}
/>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ export const DeletionDialog = React.memo((props: DeletionDialogProps) => {
title={`Delete ${titlecase(entity)} ${label}?`}
{...rest}
>
{error && <Notice error text={error} />}
<Notice warning>
{error && <Notice text={error} variant="error" />}
<Notice variant="warning">
<Typography style={{ fontSize: '0.875rem' }}>
<strong>Warning:</strong> Deleting this {entity} is permanent and
can&rsquo;t be undone.
Expand Down
2 changes: 1 addition & 1 deletion packages/manager/src/components/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const Dialog = (props: DialogProps) => {
}}
className={className}
>
{error && <Notice error text={error} />}
{error && <Notice text={error} variant="error" />}
{children}
</DialogContent>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const DismissibleBannerTemplate = (args) => {

export const CallToActionBanner = () => {
return (
<DismissibleBanner preferenceKey="cluster-v1" info>
<DismissibleBanner preferenceKey="cluster-v1" variant="info">
<Grid
container
direction="row"
Expand All @@ -67,7 +67,7 @@ export const StatusBannersTemplate = (args) => {

export const BetaBanner = () => {
return (
<DismissibleBanner preferenceKey="beta-banner" info>
<DismissibleBanner preferenceKey="beta-banner" variant="info">
<Typography>
Managed Database for MySQL is available in a free, open beta period
until May 2nd, 2022. This is a beta environment and should not be used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const DrawerContent = (props: DrawerContentProps) => {

if (error) {
return (
<Notice error spacingTop={8}>
<Notice spacingTop={8} variant="error">
{errorMessage ?? `Couldn't load ${title}`}
</Notice>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/manager/src/components/DynamicPriceNotice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Typography } from './Typography';

export const DynamicPriceNotice = (props: NoticeProps) => {
return (
<Notice info spacingBottom={0} spacingTop={12} {...props}>
<Notice spacingBottom={0} spacingTop={12} variant="info" {...props}>
<Typography fontWeight="bold">
Prices for plans, products, and services may vary based on Region.{' '}
<Link to="https://www.linode.com/pricing">Learn more.</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const LabelAndTagsPanel = (props: LabelAndTagsProps) => {
}}
data-qa-label-header
>
{error && <Notice error text={error} />}
{error && <Notice text={error} variant="error" />}
<TextField
{...(labelFieldProps || {
label: 'Label',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const MaintenanceBanner = React.memo((props: Props) => {
}

return (
<Notice important warning>
<Notice important variant="warning">
<Typography lineHeight="20px">
{generateIntroText(type, maintenanceStart, maintenanceEnd)}
</Typography>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export const MultipleIPInput = React.memo((props: Props) => {
{helperText && (
<Typography className={classes.helperText}>{helperText}</Typography>
)}
{error && <Notice error spacingTop={8} text={error} />}
{error && <Notice spacingTop={8} text={error} variant="error" />}
{ips.map((thisIP, idx) => (
<Grid
container
Expand Down
16 changes: 8 additions & 8 deletions packages/manager/src/components/Notice/Notice.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,48 +22,48 @@ Types of Notices:

<Canvas>
<Story name="Success">
<Notice success text="This is a success notice" />
<Notice variant="success" text="This is a success notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Info">
<Notice info text="This is a informational notice" />
<Notice variant="info" text="This is a informational notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Error">
<Notice error text="This is an error notice" />
<Notice variant="error" text="This is an error notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Warning">
<Notice warning text="This is a warning notice" />
<Notice variant="warning" text="This is a warning notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Important Success">
<Notice success important text="This is an important success notice" />
<Notice variant="success" important text="This is an important success notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Important Info">
<Notice info important text="This is an important informational notice" />
<Notice variant="info" important text="This is an important informational notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Important Error">
<Notice error important text="This is an important error notice" />
<Notice variant="error" important text="This is an important error notice" />
</Story>
</Canvas>

<Canvas>
<Story name="Important Warning">
<Notice warning important text="This is an important warning notice" />
<Notice variant="warning" important text="This is an important warning notice" />
</Story>
</Canvas>
61 changes: 36 additions & 25 deletions packages/manager/src/components/Notice/Notice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,29 @@ export const useStyles = makeStyles<
},
}));

export type NoticeVariant =
| 'error'
| 'info'
| 'marketing'
| 'success'
| 'warning';

export interface NoticeProps extends Grid2Props {
breakWords?: boolean;
className?: string;
dataTestId?: string;
error?: boolean;
errorGroup?: string;
flag?: boolean;
important?: boolean;
info?: boolean;
marketing?: boolean;
notificationList?: boolean;
onClick?: (e: React.MouseEvent<HTMLElement>) => void;
spacingBottom?: 0 | 4 | 8 | 12 | 16 | 20 | 24 | 32;
spacingLeft?: number;
spacingTop?: 0 | 4 | 8 | 12 | 16 | 24 | 32;
success?: boolean;
sx?: SxProps;
text?: string;
typeProps?: TypographyProps;
warning?: boolean;
variant?: NoticeVariant;
}

export const Notice = (props: NoticeProps) => {
Expand All @@ -147,22 +150,18 @@ export const Notice = (props: NoticeProps) => {
children,
className,
dataTestId,
error,
errorGroup,
flag,
important,
info,
marketing,
notificationList,
onClick,
spacingBottom,
spacingLeft,
spacingTop,
success,
sx,
text,
typeProps,
warning,
variant,
} = props;

const { classes, cx } = useStyles();
Expand All @@ -177,6 +176,14 @@ export const Notice = (props: NoticeProps) => {
</Typography>
) : null;

const variantMap = {
error: variant === 'error',
info: variant === 'info',
marketing: variant === 'marketing',
success: variant === 'success',
warning: variant === 'warning',
};

/**
* There are some cases where the message
* can be either a string or JSX. In those
Expand All @@ -198,7 +205,7 @@ export const Notice = (props: NoticeProps) => {
? `error-for-scroll-${errorGroup}`
: `error-for-scroll`;

const dataAttributes = !props.error
const dataAttributes = !variantMap.error
? {
'data-qa-notice': true,
}
Expand All @@ -211,19 +218,19 @@ export const Notice = (props: NoticeProps) => {
<Grid
className={cx({
[classes.breakWords]: breakWords,
[classes.error]: error && !notificationList,
[classes.errorList]: error && notificationList,
[classes.error]: variantMap.error && !notificationList,
[classes.errorList]: variantMap.error && notificationList,
[classes.important]: important,
[classes.info]: info && !notificationList,
[classes.infoList]: info && notificationList,
[classes.marketing]: marketing,
[classes.marketing]: marketing && !notificationList,
[classes.info]: variantMap.info && !notificationList,
[classes.infoList]: variantMap.info && notificationList,
[classes.marketing]: variantMap.marketing,
[classes.marketing]: variantMap.marketing && !notificationList,
[classes.root]: true,
[classes.success]: success && !notificationList,
[classes.successList]: success && notificationList,
[classes.warning]: warning && !notificationList,
[classes.warningList]: warning && notificationList,
[errorScrollClassName]: error,
[classes.success]: variantMap.success && !notificationList,
[classes.successList]: variantMap.success && notificationList,
[classes.warning]: variantMap.warning && !notificationList,
[classes.warningList]: variantMap.warning && notificationList,
[errorScrollClassName]: variantMap.error,
notice: true,
...(className && { [className]: true }),
})}
Expand All @@ -242,11 +249,15 @@ export const Notice = (props: NoticeProps) => {
</Grid>
)}
{important &&
((success && <Check className={classes.icon} data-qa-success-img />) ||
((warning || info) && (
((variantMap.success && (
<Check className={classes.icon} data-qa-success-img />
)) ||
((variantMap.warning || variantMap.info) && (
<Warning className={classes.icon} data-qa-warning-img />
)) ||
(error && <Error className={classes.icon} data-qa-error-img />))}
(variantMap.error && (
<Error className={classes.icon} data-qa-error-img />
)))}
<div className={classes.inner} data-testid={dataTestId}>
{innerText || _children}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export const ProductInformationBanner = React.memo(
return null;
}

const isImportantBanner =
thisBanner.decoration.important === 'true'
? true
: thisBanner.decoration.important === 'false'
? false
: true;

let hasBannerExpired = true;
try {
hasBannerExpired = isAfter(
Expand All @@ -45,7 +52,9 @@ export const ProductInformationBanner = React.memo(

return (
<DismissibleBanner
important={isImportantBanner}
preferenceKey={`${bannerLocation}-${thisBanner.expirationDate}`}
variant={thisBanner.decoration.variant ?? 'warning'}
{...rest}
>
<HighlightedMarkdown textOrMarkdown={thisBanner.message} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { Notice } from 'src/components/Notice/Notice';
import { Notice, NoticeVariant } from 'src/components/Notice/Notice';

export interface ProductNotificationProps {
onClick?: () => void;
Expand All @@ -18,8 +18,8 @@ export const ProductNotification = ({
severity,
text,
}: ProductNotificationProps) => {
const level = severityLevelMap[severity] ?? 'warning';
const props = { flag: true, [level]: true };
const level = (severityLevelMap[severity] as NoticeVariant) ?? 'warning';
const props = { flag: true, variant: level };

return <Notice {...props}>{text}</Notice>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const SelectRegionPanel = (props: SelectRegionPanelProps) => {
data-testid="region-select-warning"
spacingBottom={0}
spacingTop={8}
warning
variant="warning"
>
<Typography fontWeight="bold">
{CROSS_DATA_CENTER_CLONE_WARNING}
Expand All @@ -117,7 +117,7 @@ export const SelectRegionPanel = (props: SelectRegionPanelProps) => {
selectedID={selectedID || null}
/>
{showSelectedRegionHasDifferentPriceWarning && (
<Notice spacingBottom={0} spacingTop={12} warning>
<Notice spacingBottom={0} spacingTop={12} variant="warning">
<Typography fontWeight="bold">
The selected region has a different price structure.{' '}
<Link to="https://www.linode.com/pricing">Learn more.</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,17 @@ export const SingleTextFieldForm = React.memo((props: Props) => {
<Notice
spacingBottom={8}
spacingTop={8}
success
text={_successMessage}
variant="success"
/>
) : null}
{generalError ? (
<Notice error spacingBottom={8} spacingTop={8} text={generalError} />
<Notice
spacingBottom={8}
spacingTop={8}
text={generalError}
variant="error"
/>
) : null}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const TabbedPanel = React.memo((props: TabbedPanelProps) => {
sx={{ flexGrow: 1, ...sx }}
>
<div className={innerClass}>
{error && <Notice error>{error}</Notice>}
{error && <Notice variant="error">{error}</Notice>}
<Grid container sx={{ display: 'flex' }}>
{header !== '' && (
<Grid xs={6}>
Expand Down
Loading

0 comments on commit e88b324

Please sign in to comment.