Skip to content

Commit

Permalink
refactor: [M3-7449] - Dismissible Banner v7 story migration (#9932)
Browse files Browse the repository at this point in the history
* update imports/exports

* update comments, move styles to new file

* storybook

* some cleanup

* changeset and dismissible banner tests

* address feedback + add labels to styled components
  • Loading branch information
coliu-akamai authored Nov 27, 2023
1 parent eb5f1ef commit e6ce6c7
Show file tree
Hide file tree
Showing 18 changed files with 199 additions and 164 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tech Stories
---

Dismissible Banner V7 story migration ([#9932](https://github.com/linode/manager/pull/9932))
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DateTime } from 'luxon';
import * as React from 'react';
import { Link, useLocation } from 'react-router-dom';

import { DismissibleBanner } from 'src/components/DismissibleBanner';
import { DismissibleBanner } from 'src/components/DismissibleBanner/DismissibleBanner';
import { Typography } from 'src/components/Typography';
import { useNotificationsQuery } from 'src/queries/accountNotifications';
import { getAbuseTickets } from 'src/store/selectors/getAbuseTicket';
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as React from 'react';

import { Button } from 'src/components/Button/Button';
import { Link } from 'src/components/Link';
import { Typography } from 'src/components/Typography';

import { DismissibleBanner } from './DismissibleBanner';

import type { Meta, StoryObj } from '@storybook/react';

type Story = StoryObj<typeof DismissibleBanner>;

export const Default: Story = {
render: (args) => (
<DismissibleBanner {...args}>
<Typography>This is an example of a dismissible banner.</Typography>
</DismissibleBanner>
),
};

/**
* Example of a dismissible banner with an associated action
*/
export const CallToActionBanner: Story = {
render: () => (
<DismissibleBanner
actionButton={
<Button buttonType="primary" onClick={() => null}>
Upgrade Version
</Button>
}
preferenceKey="cluster-v1"
variant="info"
>
<Typography>A new version of Kubernetes is available.</Typography>
</DismissibleBanner>
),
};

/**
* Beta banners, along with [beta chips](/docs/elements-chips-beta-chips--default-story), provide notice to users about beta features.
*/
export const BetaBanner: Story = {
render: () => (
<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
to support production workloads. Review the{' '}
<Link to="https://www.linode.com/legal-eatp">
Early Adopter Program SLA
</Link>
.
</Typography>
</DismissibleBanner>
),
};

const meta: Meta<typeof DismissibleBanner> = {
args: { preferenceKey: 'dismissible-banner' },
component: DismissibleBanner,
title: 'Components/Notifications/Dismissible Banners',
};

export default meta;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { styled } from '@mui/material/styles';

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

import { StyledLinkButton } from '../Button/StyledLinkButton';

export const StyledNotice = styled(Notice, { label: 'StyledNotice' })(
({ theme }) => ({
'&&': {
p: {
lineHeight: '1.25rem',
},
},
alignItems: 'center',
background: theme.bg.bgPaper,
borderRadius: 1,
display: 'flex',
flexFlow: 'row nowrap',
justifyContent: 'space-between',
marginBottom: theme.spacing(),
padding: theme.spacing(2),
})
);

export const StyledButton = styled(StyledLinkButton, { label: 'StyledButton' })(
({ theme }) => ({
color: theme.textColors.tableStatic,
display: 'flex',
marginLeft: 20,
})
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { fireEvent } from '@testing-library/react';
import * as React from 'react';

import { Button } from 'src/components/Button/Button';
import { Typography } from 'src/components/Typography';
import { renderWithTheme } from 'src/utilities/testHelpers';

import { DismissibleBanner } from './DismissibleBanner';

describe('Dismissible banner', () => {
const props = {
preferenceKey: 'dismissible-banner',
};

it('renders a dismissible banner and can dismiss it', () => {
const { getByLabelText, getByText } = renderWithTheme(
<DismissibleBanner {...props}>
<Typography>This is a dismissible banner</Typography>
</DismissibleBanner>
);
const text = getByText('This is a dismissible banner');
expect(text).toBeVisible();
const dismissButton = getByLabelText('Dismiss dismissible-banner banner');
expect(dismissButton).toBeVisible();
fireEvent.click(dismissButton);
expect(dismissButton).not.toBeInTheDocument();
});
it('renders a dismissible banner with an action button', () => {
const onClickProp = {
onClick: vi.fn(),
};

const { getByText } = renderWithTheme(
<DismissibleBanner
{...props}
actionButton={
<Button {...onClickProp} buttonType="primary">
Action button
</Button>
}
>
<Typography>Banner with action button</Typography>
</DismissibleBanner>
);
const button = getByText('Action button');
expect(button).toBeVisible();
fireEvent.click(button);
expect(onClickProp.onClick).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,29 +1,63 @@
import Close from '@mui/icons-material/Close';
import Grid from '@mui/material/Unstable_Grid2';
import { styled } from '@mui/material/styles';
import { SxProps } from '@mui/system';
import * as React from 'react';

import { Box } from 'src/components/Box';
import { Notice } from 'src/components/Notice/Notice';
import {
DismissibleNotificationOptions,
useDismissibleNotifications,
} from 'src/hooks/useDismissibleNotifications';

import { StyledButton, StyledNotice } from './DismissibleBanner.styles';

import type { NoticeProps } from 'src/components/Notice/Notice';

interface Props {
/**
* Optional element to pass to the banner to trigger actions
*/
actionButton?: JSX.Element;
/**
* Child element to pass to the banner
*/
children: JSX.Element;
/**
* Additional classes to the root element
*/
className?: string;
/**
* Additional controls to pass to the Dismissible Banner
*/
options?: DismissibleNotificationOptions;
/**
* Used to check if this banner has already been dismissed
*/
preferenceKey: string;
/**
* Additional styles to apply to the root element
*/
sx?: SxProps;
}

type CombinedProps = Props & Partial<NoticeProps>;

/**
* ## Usage
*
* Banners appear between the top nav and page content and are a visual interruption of the normal page layout. Their use must be approved by all project stakeholders.
*
* ## Design
* - Banners are dismissible using an 'X' icon.
* - Consider adding a link to a doc or a guide for users to learn more.
* - Banners should be considered as one part of a larger communications plan; messaging should be developed with the marketing team.
*
* ## Variants
* Under the hood, banners use the [Notice](/docs/components-notifications-notices--success) component so they have the same variants such as:
* - Success: Informs users of a new feature or improved service.
* - Warning: Informs users of an impending change that will have an impact on their service(s).
* - Call to action: Primary Button or text link allows a user to take action directly from the banner.
*/
export const DismissibleBanner = (props: CombinedProps) => {
const {
actionButton,
Expand Down Expand Up @@ -92,26 +126,3 @@ export const useDismissibleBanner = (

return { handleDismiss, hasDismissedBanner };
};

const StyledNotice = styled(Notice)(({ theme }) => ({
'&&': {
p: {
lineHeight: '1.25rem',
},
},
alignItems: 'center',
background: theme.bg.bgPaper,
borderRadius: 1,
display: 'flex',
flexFlow: 'row nowrap',
justifyContent: 'space-between',
marginBottom: theme.spacing(),
padding: theme.spacing(2),
}));

const StyledButton = styled('button')(({ theme }) => ({
...theme.applyLinkStyles,
color: theme.textColors.tableStatic,
display: 'flex',
marginLeft: 20,
}));
1 change: 0 additions & 1 deletion packages/manager/src/components/DismissibleBanner/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ProductInformationBannerLocation } from 'src/featureFlags';
import { useFlags } from 'src/hooks/useFlags';
import { isAfter } from 'src/utilities/date';

import { DismissibleBanner } from '../DismissibleBanner';
import { DismissibleBanner } from '../DismissibleBanner/DismissibleBanner';

import type { NoticeProps } from 'src/components/Notice/Notice';

Expand Down
Loading

0 comments on commit e6ce6c7

Please sign in to comment.