feat(tools): add Alert component (#43835)

* feat(alert): initialize component

* feat(alert): add children prop

* feat(alert): add className prop

* feat(alert): add variant prop

* feat(alert): add close button and handle onDismiss click

* feat(alert): place all alert related css in alert.css

* feat: define state color variables and use them instead of bootstrap ones

* chore: remove unused classes

* feat: replace base alert styles with tailwind classes

* feat: extract close button to separate component

* chore: remove unused css

* test: add close button tests

* refactor: use more tailwind-like approach for adding colors to theme

* refactor: use more expressive prop name for close button label

* refactor: use semantic color names

* feat: add stories with/without close button

* chore: add missing variants
This commit is contained in:
Maciek Sitkowski
2021-11-27 10:28:40 +01:00
committed by GitHub
parent 32dbf3d57c
commit 58701d511b
11 changed files with 324 additions and 9 deletions

View File

@@ -0,0 +1,18 @@
import { Story } from '@storybook/react';
import React from 'react';
import { CloseButton, CloseButtonProps } from './close-button';
const story = {
title: 'Example/CloseButton',
component: CloseButton
};
const Template: Story<CloseButtonProps> = args => <CloseButton {...args} />;
export const Basic = Template.bind({});
Basic.args = {
className: '',
label: ''
};
export default story;

View File

@@ -0,0 +1,30 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { CloseButton } from './close-button';
describe('<CloseButton>', () => {
it('should render', () => {
render(<CloseButton onClick={jest.fn()} />);
expect(screen.getByRole('button')).toBeInTheDocument();
});
it('should set "aria-label" to "label" prop', () => {
const expectedLabel = 'Close me please';
render(<CloseButton label={expectedLabel} onClick={jest.fn()} />);
expect(
screen.getByRole('button', { name: expectedLabel })
).toBeInTheDocument();
});
it('should call "onClick" handler on button click', () => {
const onClick = jest.fn();
render(<CloseButton onClick={onClick} />);
userEvent.click(screen.getByRole('button'));
expect(onClick).toHaveBeenCalledTimes(1);
});
});

View File

@@ -0,0 +1,32 @@
import React from 'react';
export interface CloseButtonProps {
className?: string;
label?: string;
onClick: () => void;
}
/**
* Basic UI component for closing modals, alerts, etc.
*/
export function CloseButton({
className,
label = 'Close',
onClick
}: CloseButtonProps): JSX.Element {
const classes = [
'text-xl font-bold leading-none appearance-none opacity-20',
'hover:opacity-50 focus:opacity-50',
className
].join(' ');
return (
<button
aria-label={label}
className={classes}
onClick={onClick}
type='button'
>
×
</button>
);
}

View File

@@ -0,0 +1 @@
export { CloseButton } from './close-button';