Skip to content

Commit

Permalink
add AlertGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
Barry127 committed Nov 22, 2020
1 parent a5ee46a commit 1102202
Show file tree
Hide file tree
Showing 11 changed files with 503 additions and 9 deletions.
77 changes: 77 additions & 0 deletions pages/docs/components/Alert/AlertGroup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Description, Meta, Props } from 'docsComponents';
import { Alert } from 'maeven';

<Meta title="AlertGroup" />

# AlertGroup

<Description of="AlertGroup" />

<Alert type="warning" title="Warning!" closable={false}>
AlertGroup depends on its children to render correctly. Uncontrolled Alerts
give unpredictable results. Always use controlled Alerts!
</Alert>

## Props

<Props of="AlertGroup" />

## Examples

### Controlled

An AlertGroup of controlled Alerts.

```js live withRender
const ControlledGroup = () => {
const [showSuccess, setSuccess] = useState(true);
const [showInfo, setInfo] = useState(true);
const [showWarning, setWarning] = useState(true);
const [showDanger, setDanger] = useState(true);

return (
<AlertGroup>
<Alert
isOpen={showSuccess}
onClose={() => {
setSuccess(false);
}}
type="success"
title="Alert Title"
>
Success Alert
</Alert>
<Alert
isOpen={showInfo}
onClose={() => {
setInfo(false);
}}
type="info"
>
Info Alert
</Alert>
<Alert
isOpen={showWarning}
onClose={() => {
setWarning(false);
}}
type="warning"
>
Warning Alert
</Alert>
<Alert
isOpen={showDanger}
onClose={() => {
setDanger(false);
}}
type="danger"
closable={false}
>
Danger Alert (always closable in group)
</Alert>
</AlertGroup>
);
};

render(<ControlledGroup />);
```
3 changes: 2 additions & 1 deletion pages/docs/nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"Alert": {
"basePath": "/docs/components/Alert",
"children": {
"Alert": "/docs/components/Alert/Alert"
"Alert": "/docs/components/Alert/Alert",
"AlertGroup": "/docs/components/Alert/AlertGroup"
}
},
"Block": "/docs/components/Block",
Expand Down
54 changes: 50 additions & 4 deletions src/common/defaultIcons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { MaevenIcon } from '../types';
/**
* Default Icons used for components.
*
* check, chevronDown, chevronUp, close, danger, info,
* minus, passwordShow, passwordHide, success, warning
* icons are licensed under the MIT License by Feather
* Icons: https://feathericons.com
* check, chevronDown, ChevronLeft, ChevronRight chevronUp,
* close, danger, info,minus, passwordShow, passwordHide,
* success, warning icons are licensed under the MIT
* License by Feather Icons: https://feathericons.com
*/

export const check: MaevenIcon = {
Expand Down Expand Up @@ -55,6 +55,52 @@ export const chevronDown: MaevenIcon = {
]
};

export const chevronLeft: MaevenIcon = {
tag: 'svg',
attrs: {
xmlns: 'http://www.w3.org/2000/svg',
width: 24,
height: 24,
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
strokeWidth: 2,
strokeLinecap: 'round',
strokeLinejoin: 'round'
},
children: [
{
tag: 'polyline',
attrs: {
points: '15 18 9 12 15 6'
}
}
]
};

export const chevronRight: MaevenIcon = {
tag: 'svg',
attrs: {
xmlns: 'http://www.w3.org/2000/svg',
width: 24,
height: 24,
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
strokeWidth: 2,
strokeLinecap: 'round',
strokeLinejoin: 'round'
},
children: [
{
tag: 'polyline',
attrs: {
points: '9 18 15 12 9 6'
}
}
]
};

export const chevronUp: MaevenIcon = {
tag: 'svg',
attrs: {
Expand Down
12 changes: 8 additions & 4 deletions src/components/Alert/Alert/alert.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ $alert-types: (

.content {
flex-grow: 1;

.title {
color: inherit;
}
}

.close {
Expand All @@ -45,18 +49,18 @@ $alert-types: (
@each $name, $color in $alert-types {
.#{$name} {
border-color: var(--mvn-#{$color});
background: var(--mvn-#{$color}-w85);
background-color: var(--mvn-#{$color}-w85);

.icon {
color: var(--mvn-color-text-#{$color});
}

:global(.mvn-dark) & {
background: var(--mvn-#{$color});
color: var(--mvn-color-text-background-#{$color});
background-color: var(--mvn-#{$color});
color: var(--mvn-#{$color}-background-text);

.icon {
color: var(--mvn-color-text-background-#{$color});
color: var(--mvn-#{$color}-background-text);
}
}
}
Expand Down
199 changes: 199 additions & 0 deletions src/components/Alert/AlertGroup/AlertGroup.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import { act, fireEvent, render } from '@testing-library/react';
import { circle as circleIcon } from 'icon-packs/cjs/feather';
import React, { createRef } from 'react';
import maeven from '../../../themes/maeven';
import { ThemeProvider } from '../../ThemeProvider';
import { Alert } from '../Alert';
import { AlertGroup } from './AlertGroup';

describe('AlertGroup', () => {
it('renders div element with given children', () => {
render(
<AlertGroup>
<Alert closable={false}>Alert 1</Alert>
<Alert type="success">Alert 2</Alert>
<p>Alert 3</p>
</AlertGroup>
);
const element = document.querySelector('.mvn--alert-group');
expect(element?.tagName).toBe('DIV');
expect(element).toHaveTextContent('1 / 2Alert 1');
});

it('sets className', () => {
render(
<AlertGroup className="alert-group-class">
<Alert />
</AlertGroup>
);
const element = document.querySelector('.mvn--alert-group');
expect(element).toHaveClass('alert-group-class');
});

it('passes props', () => {
render(
<AlertGroup id="AlertGroupId" data-test="alert-group-data">
<Alert />
</AlertGroup>
);
const element = document.querySelector('.mvn--alert-group');
expect(element).toHaveAttribute('id', 'AlertGroupId');
expect(element).toHaveAttribute('data-test', 'alert-group-data');
});

it('makes alert always closable', () => {
render(
<AlertGroup>
<Alert closable={false}>Alert 1</Alert>
</AlertGroup>
);
const closeButton = document.querySelector('button');
expect(closeButton).toBeInTheDocument();
});

it('navigates between alerts', () => {
render(
<AlertGroup>
<Alert closable={false}>Alert 1</Alert>
<Alert type="success">Alert 2</Alert>
<p>Alert 3</p>
</AlertGroup>
);

const element = document.querySelector('.mvn--alert-group');
const buttons = document.querySelectorAll('button');
const prev = buttons[0] as HTMLButtonElement;
const next = buttons[1] as HTMLButtonElement;

expect(element).toHaveTextContent('1 / 2Alert 1');

act(() => {
fireEvent.click(next);
});

expect(element).toHaveTextContent('2 / 2Alert 2');

act(() => {
fireEvent.click(next);
});

expect(element).toHaveTextContent('1 / 2Alert 1');

act(() => {
fireEvent.click(prev);
});

expect(element).toHaveTextContent('2 / 2Alert 2');
});

it('filters non-Alert children out', () => {
render(
<AlertGroup>
<Alert closable={false}>Alert 1</Alert>
<Alert type="success">Alert 2</Alert>
<p>Alert 3</p>
</AlertGroup>
);

const nav = document.querySelector('.nav');
expect(nav).toHaveTextContent('1 / 2');
});

it('does not render nav with only one Alert child', () => {
render(
<AlertGroup>
<Alert>Alert 1</Alert>
</AlertGroup>
);

const nav = document.querySelector('.nav');
expect(nav).not.toBeInTheDocument();
});

it('does not render an AlertGroup when there are no Children', () => {
render(<AlertGroup />);
const element = document.querySelector('.mvn--alert-group');
expect(element).not.toBeInTheDocument();
});

describe('chevronLeft icon', () => {
it('defaults to chevronLeft', () => {
render(
<AlertGroup>
<Alert showIcon={false} />
<Alert showIcon={false} />
</AlertGroup>
);
const circle = document.querySelectorAll('circle');
const polyline = document.querySelectorAll('polyline');
expect(circle).toHaveLength(0);
expect(polyline).toHaveLength(2);
});

it('overrides chevronLeft icon from theme', () => {
const theme = {
...maeven,
iconOverrides: {
chevronLeft: circleIcon
}
};
render(
<ThemeProvider theme={theme}>
<AlertGroup>
<Alert showIcon={false} />
<Alert showIcon={false} />
</AlertGroup>
</ThemeProvider>
);
const circle = document.querySelectorAll('circle');
const polyline = document.querySelectorAll('polyline');
expect(circle).toHaveLength(1);
expect(polyline).toHaveLength(1);
});
});

describe('chevronRight icon', () => {
it('defaults to chevronRight', () => {
render(
<AlertGroup>
<Alert showIcon={false} />
<Alert showIcon={false} />
</AlertGroup>
);
const circle = document.querySelectorAll('circle');
const polyline = document.querySelectorAll('polyline');
expect(circle).toHaveLength(0);
expect(polyline).toHaveLength(2);
});

it('overrides chevronRight icon from theme', () => {
const theme = {
...maeven,
iconOverrides: {
chevronRight: circleIcon
}
};
render(
<ThemeProvider theme={theme}>
<AlertGroup>
<Alert showIcon={false} />
<Alert showIcon={false} />
</AlertGroup>
</ThemeProvider>
);
const circle = document.querySelectorAll('circle');
const polyline = document.querySelectorAll('polyline');
expect(circle).toHaveLength(1);
expect(polyline).toHaveLength(1);
});
});

describe('forwarding ref', () => {
it('sets ref', () => {
const ref = createRef<HTMLDivElement>();
render(<AlertGroup ref={ref} />);
const element = document.querySelector('.mvn--alert-group');
expect(ref.current).toBe(element);
});
});
});
Loading

0 comments on commit 1102202

Please sign in to comment.