Skip to content

Commit

Permalink
Merge pull request #25 from user-interviews/feature/UIDS-24-flash-com…
Browse files Browse the repository at this point in the history
…ponent

UIDS-24 Flash message components
  • Loading branch information
rsaris authored Mar 25, 2020
2 parents 8c235f6 + 2253e5a commit 02cbdfd
Show file tree
Hide file tree
Showing 22 changed files with 2,231 additions and 3,171 deletions.
8 changes: 4 additions & 4 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"browser": true
},
"parser": "babel-eslint",
"plugins": [ "babel", "react" ],
"plugins": [ "babel", "react", "react-hooks" ],
"rules": {
"babel/semi": 2,
"import/prefer-default-export": 0,
Expand All @@ -33,9 +33,7 @@
"no-alert": 0,
"react/destructuring-assignment": 0,
"react/forbid-prop-types": 0,
"react/jsx-props-no-spreading": [2, {
"html": "ignore"
}],
"react/jsx-props-no-spreading": 0,
"react/jsx-no-target-blank": 1,
"react/jsx-no-undef": 0,
"react/jsx-one-expression-per-line": 0,
Expand Down Expand Up @@ -102,6 +100,8 @@
"requiredFirst": false,
"sortShapeProp": true
}],
"react-hooks/exhaustive-deps": "warn",
"react-hooks/rules-of-hooks": "error",
"semi": 0
},
}
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ lib
.env.test.local
.env.production.local

# Ignore Jetbrains IDE settings
/.idea

npm-debug.log*
yarn-debug.log*
yarn-error.log*
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"node-sass": "^4.13.1",
"polished": "^3.4.2",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-dom": "^16.12.0"
"react-transition-group": "^4.3.0",
"uuid": "^7.0.2"
},
"scripts": {
"build": "NODE_ENV=production babel src --out-dir lib --copy-files",
Expand All @@ -35,6 +35,10 @@
"last 1 safari version"
]
},
"peerDependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.4",
Expand All @@ -51,6 +55,7 @@
"@storybook/addons": "^5.3.13",
"@storybook/react": "^5.3.13",
"@storybook/storybook-deployer": "^2.8.1",
"@testing-library/react-hooks": "^3.2.1",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
Expand All @@ -63,7 +68,10 @@
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.3",
"eslint-plugin-react-hooks": "^2.5.1",
"eslint-utils": "^1.4.3",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-test-renderer": "^16.12.0",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3"
Expand Down
9 changes: 9 additions & 0 deletions scss/box_shadow.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
$ux-navbar-shadow-color: rgba( 0, 0, 0, 0.26 );

$ux-box-shadow: 0 2px 5px $ux-navbar-shadow-color;
$ux-box-shadow-light: 0 1px 1px $ux-navbar-shadow-color;

$ux-box-shadow-card: 0 2px 4px rgba(0,0,0,0.1);

$ux-box-shadow-top: 0 -2px 5px $ux-navbar-shadow-color;
$ux-box-shadow-top-light: 0 -1px 1px $ux-navbar-shadow-color;
2 changes: 2 additions & 0 deletions scss/navbar.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$ui-navbar-height: 3rem;
$ui-navbar-height-mobile: $ui-navbar-height;
2 changes: 2 additions & 0 deletions scss/theme.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@import './box_shadow';
@import './lists';
@import './navbar';
@import './palette';
@import './typography';
@import './z_stack';
20 changes: 20 additions & 0 deletions spec/Flash/Flash.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { create } from 'react-test-renderer';

import Flash from '../../src/Flash/Flash';

describe('Flash', () => {
test('no header classes', () => {
const { props } = create(<Flash header messages={[]} />).toJSON();

expect(props.className).toContain('Flash');
expect(props.className).not.toContain('Flash--no-header');
});

test('header classes', () => {
const { props } = create(<Flash header={false} messages={[]} />).toJSON();

expect(props.className).toContain('Flash');
expect(props.className).toContain('Flash--no-header');
});
});
19 changes: 19 additions & 0 deletions spec/Flash/__snapshots__/withFlash.test.jsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`test withFlash it can create a new flash message 1`] = `
Array [
<div
className="alert alert-success"
>
<button
className="close"
onClick={[Function]}
type="button"
>
×
</button>
This is just a test...
</div>,
<div />,
]
`;
88 changes: 88 additions & 0 deletions spec/Flash/useFlash.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { renderHook, act } from '@testing-library/react-hooks';
import { MessageTypes, useFlash } from '../../src/Flash';

const GENERATED_UUID = '1234';

jest.mock('uuid', () => (
{
v4: () => '1234',
}
));

describe('useFlash', () => {
test('can set a new message', () => {
const newMessage = 'I want to say something!';
const { result } = renderHook(() => useFlash());

act(() => {
result.current.setMessage(MessageTypes.SUCCESS, newMessage);
});

expect(result.current.messages).toEqual([{
id: GENERATED_UUID,
type: MessageTypes.SUCCESS,
message: newMessage,
}]);
});

test('can dismiss an existing message', () => {
const newMessage = 'I want to say something else!';
const { result } = renderHook(() => useFlash());

act(() => {
result.current.setMessage(MessageTypes.SUCCESS, newMessage);
});

expect(result.current.messages).toEqual([{
id: GENERATED_UUID,
type: MessageTypes.SUCCESS,
message: newMessage,
}]);

act(() => {
result.current.dismissMessage(GENERATED_UUID);
});

expect(result.current.messages).toEqual([]);
});

test('can set two messages', () => {
const newMessages = ['I want to say', 'so many things'];
const { result } = renderHook(() => useFlash());

newMessages.forEach(
(message) => {
act(() => {
result.current.setMessage(MessageTypes.ERROR, message);
});
},
);

expect(result.current.messages).toEqual(
newMessages.map((message) => ({
id: GENERATED_UUID,
type: MessageTypes.ERROR,
message,
})),
);
});

test('can clear all messages', () => {
const messages = ['A new', 'message'].map(
(msg, i) => ({
id: i,
type: MessageTypes.SUCCESS,
message: msg,
}),
);

const { result } = renderHook(() => useFlash(messages));
expect(result.current.messages.length).toEqual(2);

act(() => {
result.current.clearMessages();
});

expect(result.current.messages.length).toEqual(0);
});
});
30 changes: 30 additions & 0 deletions spec/Flash/withFlash.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { act } from '@testing-library/react-hooks';
import { create } from 'react-test-renderer';

import withFlash from '../../src/Flash/withFlash';
import { MessageTypes } from '../../src/Flash';

jest.mock('react-transition-group', () => (
{
CSSTransition: ({ children }) => children,
TransitionGroup: ({ children }) => children,
}
));

const WrappedComponent = () => <div />;

describe('test withFlash', () => {
test('it can create a new flash message', async () => {
const newMessage = 'This is just a test...';
const ComponentWithFlash = withFlash(WrappedComponent);
const flash = create(<ComponentWithFlash />);
const component = flash.root.findByType(WrappedComponent);

act(() => {
component.props.setFlashMessage(MessageTypes.SUCCESS, newMessage);
});

expect(flash).toMatchSnapshot();
});
});
52 changes: 52 additions & 0 deletions spec/__snapshots__/Storyshots.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,58 @@ exports[`Storyshots Design System/Card all cards 1`] = `
</div>
`;

exports[`Storyshots Design System/Flash Flash Message 1`] = `
<div
style={
Object {
"padding": "1rem",
}
}
>
<div
className="container Flash"
/>
<div>
<p>
Click the button to see a flash message. Use the knobs to try different types!
</p>
<button
className="btn btn-primary"
onClick={[Function]}
type="button"
>
Submit
</button>
</div>
</div>
`;

exports[`Storyshots Design System/Flash flash message 1`] = `
<div
style={
Object {
"padding": "1rem",
}
}
>
<div
className="container flash"
/>
<div>
<p>
Click the button to see a flash message. Use the knobs to try different types!
</p>
<button
className="btn btn-primary"
onClick={[Function]}
type="button"
>
Submit
</button>
</div>
</div>
`;

exports[`Storyshots Design System/Form Control Label Radio 1`] = `
<div
style={
Expand Down
17 changes: 17 additions & 0 deletions src/FadeTransition/FadeTransition.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import { CSSTransition } from 'react-transition-group';

import './FadeTransition.scss';

const FadeTransition = ({ children, ...props }) => (
<CSSTransition {...props} classNames="FadeTransition" timeout={{ enter: 300, exit: 200 }}>
{children}
</CSSTransition>
);

FadeTransition.propTypes = {
children: PropTypes.element.isRequired,
};

export default FadeTransition;
17 changes: 17 additions & 0 deletions src/FadeTransition/FadeTransition.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.FadeTransition-enter {
opacity: 0.01;

&.FadeTransition-enter-active {
opacity: 1;
transition: opacity 300ms ease-in;
}
}

.FadeTransition-exit {
opacity: 1;

&.FadeTransition-exit-active {
opacity: 0.01;
transition: opacity 200ms ease-in;
}
}
Loading

0 comments on commit 02cbdfd

Please sign in to comment.