diff --git a/src/components/alert/__snapshots__/alert.test.tsx.snap b/src/components/alert/__snapshots__/alert.test.tsx.snap
new file mode 100644
index 0000000..d648c0f
--- /dev/null
+++ b/src/components/alert/__snapshots__/alert.test.tsx.snap
@@ -0,0 +1,245 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`IonAlert should render alert with type: info 1`] = `
+.c0 {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ font-size: 1.4rem;
+ line-height: 2rem;
+ font-weight: 400;
+ color: #282b33;
+ border-radius: 8px;
+ height: 4rem;
+ padding: 8px 16px 8px 12px;
+ border: 1px solid #0bb2cb;
+ background-color: #e2f9fd;
+ border-left: 8px solid #0bb2cb;
+}
+
+.c0 .c1 svg {
+ fill: #0bb2cb;
+}
+
+.c2 {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+
+
+
+
+
+ Example message
+
+
+
+
+`;
+
+exports[`IonAlert should render alert with type: negative 1`] = `
+.c0 {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ font-size: 1.4rem;
+ line-height: 2rem;
+ font-weight: 400;
+ color: #282b33;
+ border-radius: 8px;
+ height: 4rem;
+ padding: 8px 16px 8px 12px;
+ border: 1px solid #d6293a;
+ background-color: #faeaec;
+ border-left: 8px solid #d6293a;
+}
+
+.c0 .c1 svg {
+ fill: #d6293a;
+}
+
+.c2 {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+
+
+
+
+
+ Example message
+
+
+
+
+`;
+
+exports[`IonAlert should render alert with type: success 1`] = `
+.c0 {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ font-size: 1.4rem;
+ line-height: 2rem;
+ font-weight: 400;
+ color: #282b33;
+ border-radius: 8px;
+ height: 4rem;
+ padding: 8px 16px 8px 12px;
+ border: 1px solid #2d9f70;
+ background-color: #e7f9f1;
+ border-left: 8px solid #2d9f70;
+}
+
+.c0 .c1 svg {
+ fill: #2d9f70;
+}
+
+.c2 {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+
+
+
+
+
+ Example message
+
+
+
+
+`;
+
+exports[`IonAlert should render alert with type: warning 1`] = `
+.c0 {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ font-size: 1.4rem;
+ line-height: 2rem;
+ font-weight: 400;
+ color: #282b33;
+ border-radius: 8px;
+ height: 4rem;
+ padding: 8px 16px 8px 12px;
+ border: 1px solid #f9a915;
+ background-color: #fff5e0;
+ border-left: 8px solid #f9a915;
+}
+
+.c0 .c1 svg {
+ fill: #f9a915;
+}
+
+.c2 {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+
+
+
+
+
+ Example message
+
+
+
+
+`;
diff --git a/src/components/alert/alert.test.tsx b/src/components/alert/alert.test.tsx
index 6cc300c..cc80f51 100644
--- a/src/components/alert/alert.test.tsx
+++ b/src/components/alert/alert.test.tsx
@@ -1,15 +1,15 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
+import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import { IonAlert, AlertProps } from './alert';
import { StatusType } from '../../core/types/status';
+import { renderWithTheme } from '../utils/test-utils';
+import { AlertProps, IonAlert } from './alert';
const defaultAlert: AlertProps = {
message: 'Example message',
};
-const sut = (props = defaultAlert) => render();
+const sut = (props = defaultAlert) => renderWithTheme();
const alertId = 'ion-alert';
const getAlert = () => screen.getByTestId(alertId);
@@ -36,14 +36,17 @@ describe('IonAlert', () => {
it.each(['success', 'info', 'warning', 'negative'] as StatusType[])(
'should render alert with type: %s',
(type) => {
- sut({ ...defaultAlert, type });
- expect(getAlert().className).toContain(`type-${type}`);
+ const { container } = sut({ ...defaultAlert, type });
+ expect(container).toMatchSnapshot();
}
);
it('should not render background alert when hideBackground is true', async () => {
await sut({ ...defaultAlert, hideBackground: true });
- expect(getAlert().className).toContain('hideBackground-true');
+ expect(getAlert()).not.toHaveStyleRule(
+ 'background-color',
+ expect.any(String)
+ );
});
it('should render icon close when closable is true', async () => {
@@ -52,12 +55,11 @@ describe('IonAlert', () => {
expect(iconClose).toBeTruthy();
});
- it('should remove alert when click on close icon', async () => {
- await sut({ ...defaultAlert, closable: true });
- const iconClose = screen.getByTestId('ion-icon-close');
- expect(getAlert()).toBeTruthy();
+ it('should emit onClose function when click on close icon', async () => {
+ const onClose = jest.fn();
+ await sut({ ...defaultAlert, closable: true, onClose });
- await userEvent.click(iconClose);
- expect(screen.queryByTestId(alertId)).not.toBeTruthy();
+ await userEvent.click(screen.getByTestId('ion-icon-close'));
+ expect(onClose).toHaveBeenCalledTimes(1);
});
});
diff --git a/src/components/alert/alert.tsx b/src/components/alert/alert.tsx
index d556d55..2c15795 100644
--- a/src/components/alert/alert.tsx
+++ b/src/components/alert/alert.tsx
@@ -1,16 +1,17 @@
-import { useState } from 'react';
import { StatusType } from '../../core/types/status';
+import { IonButton } from '../button';
import ErrorBoundary from '../error/error-boundary';
import { IonIcon } from '../icons/icons';
import isValidLabel from '../utils/isValidLabel';
-import { AlertStyled } from './styled';
+import { Alert, Wrapper } from './styled';
export interface AlertProps {
message: string;
type?: StatusType;
closable?: boolean;
hideBackground?: boolean;
+ onClose?: () => void;
}
type iconType =
@@ -19,47 +20,48 @@ type iconType =
| 'info-solid'
| 'close-solid';
-const icons = {
+const icons: Record = {
info: 'info-solid',
warning: 'exclamation-solid',
negative: 'close-solid',
success: 'check-solid',
};
-const sizeIcon = 24;
+const SIZE_ICON = 24;
-const getIcon = (alertType: StatusType) => icons[alertType] as iconType;
+const getIcon = (alertType: StatusType): iconType => icons[alertType];
export const IonAlert = ({
message,
type = 'success',
closable = false,
hideBackground = false,
+ onClose,
}: AlertProps) => {
- const [showAlert, setShowAlert] = useState(true);
- const icon = getIcon(type);
-
if (!isValidLabel(message)) {
return ;
}
- if (!showAlert) {
- return <>>;
- }
-
return (
-
-
- {message}
+
+
+ {message}
+
{closable && (
- setShowAlert(false)}>
-
-
+
)}
-
+
);
};
diff --git a/src/components/alert/styled.ts b/src/components/alert/styled.ts
index 639ae7c..64f3970 100644
--- a/src/components/alert/styled.ts
+++ b/src/components/alert/styled.ts
@@ -1,88 +1,48 @@
-import stitches from '../../stitches.config';
-import { getFillBgFontBorderColors } from '../utils';
-import { spacing } from '../utils/spacing';
-
-const { styled } = stitches;
-
-export const AlertStyled = styled('div', {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- padding: `${spacing(1)} ${spacing(2)} ${spacing(1)} ${spacing(1.5)}`,
- gap: spacing(1),
-
- minHeight: 24,
-
- backgroundColor: '$positive1',
-
- borderWidth: '1px 1px 1px 8px',
- borderStyle: 'solid',
- borderColor: '$positive6',
- borderRadius: 8,
-
- fontSize: 14,
- fontWeight: 400,
- color: '$neutral8',
-
- svg: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- gap: spacing(1),
-
- fill: '$primary6',
-
- borderRadius: 9,
- },
-
- span: {
- width: '95%',
- },
-
- '& svg:last-child': {
- fill: '$primary6',
- },
-
- variants: {
- type: {
- info: {
- ...getFillBgFontBorderColors({
- backgroundColor: '$info1',
- borderColor: '$info6',
- svgFillColor: '$info6',
- fontColor: '$neutral8',
- }),
- },
- warning: {
- ...getFillBgFontBorderColors({
- backgroundColor: '$warning1',
- borderColor: '$warning6',
- svgFillColor: '$warning6',
- fontColor: '$neutral8',
- }),
- },
- negative: {
- ...getFillBgFontBorderColors({
- backgroundColor: '$negative1',
- borderColor: '$negative6',
- svgFillColor: '$negative6',
- fontColor: '$neutral8',
- }),
- },
- success: {
- ...getFillBgFontBorderColors({
- backgroundColor: '$positive1',
- borderColor: '$positive6',
- svgFillColor: '$positive6',
- fontColor: '$neutral8',
- }),
- },
- },
- hideBackground: {
- true: {
- backgroundColor: 'transparent !important',
- borderColor: 'transparent !important',
- },
- },
- },
-});
+import { StatusType } from '@ion/core/types/status';
+import { css, styled } from 'styled-components';
+
+type AlertStyledProps = {
+ $type: StatusType;
+ $hideBackground: boolean;
+ $closable: boolean;
+};
+
+const getColorsType = (type: StatusType) => {
+ return {
+ success: 'positive',
+ info: 'info',
+ warning: 'warning',
+ negative: 'negative',
+ }[type] as 'positive' | 'info' | 'warning' | 'negative';
+};
+
+export const Alert = styled.div`
+ ${({ theme, $type, $hideBackground, $closable }) => css`
+ ${theme.utils.flex.spaceBetween(8)};
+ ${theme.font.size[14]}
+ font-weight: 400;
+ color: ${theme.colors.neutral[8]};
+ border-radius: 8px;
+
+ ${!$hideBackground &&
+ css`
+ height: 4rem;
+ padding: 8px ${$closable ? '16px' : '16px 8px 12px'};
+ border: 1px solid ${theme.colors[getColorsType($type)][6]};
+ background-color: ${!$hideBackground &&
+ theme.colors[getColorsType($type)][1]};
+ ${!$closable &&
+ `border-left: 8px solid ${theme.colors[getColorsType($type)][6]}`};
+ `}
+
+ ${Wrapper} svg {
+ fill: ${theme.colors[getColorsType($type)][6]};
+ }
+ `}
+`;
+
+export const Wrapper = styled.div`
+ ${({ theme }) => css`
+ ${theme.utils.flex.center(8)}
+ `}
+`;