From 548657c6715801f3775f164e5fa8ec4e4438d447 Mon Sep 17 00:00:00 2001 From: Adam Kudrna Date: Sat, 6 Jun 2020 00:06:39 +0200 Subject: [PATCH] Make `Alert`s dismissible (#11) --- src/demo/pages/DemoContainer.jsx | 127 +++++++++++------- src/lib/components/ui/Alert/Alert.jsx | 76 +++++++---- src/lib/components/ui/Alert/Alert.scss | 53 ++++++-- src/lib/components/ui/Alert/_mixins.scss | 14 +- src/lib/components/ui/Alert/_theme.scss | 1 - src/lib/components/ui/Alert/_variables.scss | 9 +- .../components/ui/Alert/tests/Alert.test.jsx | 20 +++ .../tests/__snapshots__/Alert.test.jsx.snap | 20 ++- .../ui/Modal/__tests__/Modal.test.jsx | 1 - src/lib/theme.scss | 2 +- 10 files changed, 216 insertions(+), 107 deletions(-) diff --git a/src/demo/pages/DemoContainer.jsx b/src/demo/pages/DemoContainer.jsx index 3d6f4c5f..b25ceb4a 100644 --- a/src/demo/pages/DemoContainer.jsx +++ b/src/demo/pages/DemoContainer.jsx @@ -864,57 +864,90 @@ class DemoContainer extends React.Component { - - - Success: - Success message - - - - - Warning: - Warning message - - - - - Error: - Error message - - - - - Info: - Info message - - - - - Help: - Help message - - - - - Note: - Note message - - - + <> +
+ + + Success: + Success message + + +
+
+ + + Warning: + Warning message + + +
+
+ + + Error: + Error message + + +
+
+ + + Info: + Info message + + +
+
+ + + Help: + Help message + + +
+
+ + + Note: + Note message + + +
+ )} /> - }> - - Success: - Success message - - - + } + type="success" + > + + Success: + Success message + + + )} + /> + } + type="success" + > + + Success: + Curabitur sagittis hendrerit ante. Integer pellentesque quam vel velit. Sed vel + lectus. Donec odio tempus molestie, porttitor ut, iaculis quis, sem. + Pellentesque sapien. Ut enim ad minima veniam, quis nostrum exercitationem ullam + corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? + Maecenas sollicitudin. + + )} />

Badge

diff --git a/src/lib/components/ui/Alert/Alert.jsx b/src/lib/components/ui/Alert/Alert.jsx index 8c97d46e..c645cd6d 100644 --- a/src/lib/components/ui/Alert/Alert.jsx +++ b/src/lib/components/ui/Alert/Alert.jsx @@ -3,47 +3,76 @@ import React from 'react'; import styles from './Alert.scss'; const Alert = (props) => { - let rootTypeClass = styles.note; - - if (props.type) { - if (props.type === 'success') { - rootTypeClass = styles.success; - } else if (props.type === 'error') { - rootTypeClass = styles.error; - } else if (props.type === 'warning') { - rootTypeClass = styles.warning; - } else if (props.type === 'info') { - rootTypeClass = styles.info; - } else if (props.type === 'help') { - rootTypeClass = styles.help; + const { + children, + closeHandler, + icon, + id, + type, + } = props; + + const rootTypeClass = (variant) => { + if (variant === 'success') { + return styles.isRootSuccess; + } + + if (variant === 'error') { + return styles.isRootError; } - } + + if (variant === 'warning') { + return styles.isRootWarning; + } + + if (variant === 'info') { + return styles.isRootInfo; + } + + if (variant === 'help') { + return styles.isRootHelp; + } + + return styles.isRootNote; + }; return ( ); }; Alert.defaultProps = { + closeHandler: null, icon: null, id: undefined, type: 'note', @@ -51,6 +80,7 @@ Alert.defaultProps = { Alert.propTypes = { children: PropTypes.node.isRequired, + closeHandler: PropTypes.func, icon: PropTypes.node, id: PropTypes.string, type: PropTypes.oneOf(['error', 'help', 'info', 'note', 'success', 'warning']), diff --git a/src/lib/components/ui/Alert/Alert.scss b/src/lib/components/ui/Alert/Alert.scss index 4c090051..d8e4f467 100644 --- a/src/lib/components/ui/Alert/Alert.scss +++ b/src/lib/components/ui/Alert/Alert.scss @@ -1,20 +1,37 @@ +@import '../../../styles/tools/offset'; @import 'mixins'; .root { - @include alert(); + position: relative; + display: flex; + align-items: flex-start; + width: 100%; + border-width: $alert-border-width $alert-border-width $alert-border-width $alert-stripe-width; + border-style: solid; + border-radius: $alert-border-radius; +} + +.close, +.icon, +.message { + padding: $alert-padding; +} + +.close, +.icon { + height: $alert-min-height; } .icon { display: flex; flex: none; align-items: center; - align-self: flex-start; justify-content: center; - height: calc(#{$alert-line-height} * #{$alert-font-size}); + padding-right: 0; } .message { - padding-left: $alert-padding; + flex-grow: 1; font-weight: $alert-message-font-weight; font-size: $alert-font-size; line-height: $alert-line-height; @@ -24,26 +41,42 @@ font-weight: $alert-title-font-weight; } -.success { +.close { + font-size: map-get($typography-size-values, 3); + line-height: 1; + border: 0; + background: none; + box-shadow: none; + appearance: none; + user-select: none; + cursor: pointer; +} + +.closeSign { + position: relative; + top: -0.1em; +} + +.isRootSuccess { @include alert-type(success); } -.warning { +.isRootWarning { @include alert-type(warning); } -.error { +.isRootError { @include alert-type(error); } -.info { +.isRootInfo { @include alert-type(info); } -.help { +.isRootHelp { @include alert-type(help); } -.note { +.isRootNote { @include alert-type(note); } diff --git a/src/lib/components/ui/Alert/_mixins.scss b/src/lib/components/ui/Alert/_mixins.scss index 52220d8b..46054d8c 100644 --- a/src/lib/components/ui/Alert/_mixins.scss +++ b/src/lib/components/ui/Alert/_mixins.scss @@ -1,17 +1,4 @@ -@import '../../../styles/tools/breakpoints'; @import 'variables'; -@import 'theme'; - -@mixin alert() { - position: relative; - display: flex; - width: 100%; - min-height: $alert-min-height; - padding: $alert-padding; - border-width: $alert-border-width $alert-border-width $alert-border-width $alert-stripe-width; - border-style: solid; - border-radius: $alert-border-radius; -} @mixin alert-type($type) { $type-properties: map-get($alert-types, $type); @@ -22,6 +9,7 @@ background-color: map-get($type-properties, background-color); strong, + .close, .icon { color: $foreground-color; } diff --git a/src/lib/components/ui/Alert/_theme.scss b/src/lib/components/ui/Alert/_theme.scss index 980acc3d..fd46ae33 100644 --- a/src/lib/components/ui/Alert/_theme.scss +++ b/src/lib/components/ui/Alert/_theme.scss @@ -1,7 +1,6 @@ $alert-border-width: var(--rui-alert-border-width); $alert-border-radius: var(--rui-alert-border-radius); $alert-padding: var(--rui-alert-padding); -$alert-icon-size: var(--rui-icon-size-default); $alert-types: ( success: ( diff --git a/src/lib/components/ui/Alert/_variables.scss b/src/lib/components/ui/Alert/_variables.scss index d7dffde1..5c52fbb0 100644 --- a/src/lib/components/ui/Alert/_variables.scss +++ b/src/lib/components/ui/Alert/_variables.scss @@ -1,14 +1,9 @@ -@import '../../../styles/settings/colors'; -@import '../../../styles/settings/offsets'; @import '../../../styles/settings/typography'; @import './theme'; $alert-font-size: map-get($typography-size-values, 0); -$alert-line-height: 1.2; -$alert-min-height: - calc( - #{$alert-font-size} * #{$alert-line-height} + 2 * #{$alert-padding} + 2 * #{$alert-border-width} - ); +$alert-line-height: 1.5; +$alert-min-height: calc(#{$alert-font-size} * #{$alert-line-height} + 2 * #{$alert-padding}); $alert-stripe-width: 5px; $alert-message-font-weight: map-get($typography-font-weight-values, light); $alert-title-font-weight: map-get($typography-font-weight-values, bold); diff --git a/src/lib/components/ui/Alert/tests/Alert.test.jsx b/src/lib/components/ui/Alert/tests/Alert.test.jsx index ae591852..f418c0eb 100644 --- a/src/lib/components/ui/Alert/tests/Alert.test.jsx +++ b/src/lib/components/ui/Alert/tests/Alert.test.jsx @@ -1,5 +1,7 @@ import React from 'react'; +import sinon from 'sinon'; import { + mount, shallow, } from 'enzyme'; import { shallowToJson } from 'enzyme-to-json'; @@ -21,6 +23,7 @@ describe('rendering', () => { it('renders correctly with all props', () => { const tree = shallow( {}} icon={} id="custom-id" message="Message" @@ -33,3 +36,20 @@ describe('rendering', () => { expect(shallowToJson(tree)).toMatchSnapshot(); }); }); + +describe('functionality', () => { + it('calls closeHandler() on Close button click', () => { + const spy = sinon.spy(); + const component = mount(( + +
Children
+
+ )); + + component.find('button').at(0).simulate('click'); + expect(spy.calledOnce).toEqual(true); + }); +}); diff --git a/src/lib/components/ui/Alert/tests/__snapshots__/Alert.test.jsx.snap b/src/lib/components/ui/Alert/tests/__snapshots__/Alert.test.jsx.snap index 638e68ea..a6ddfce3 100644 --- a/src/lib/components/ui/Alert/tests/__snapshots__/Alert.test.jsx.snap +++ b/src/lib/components/ui/Alert/tests/__snapshots__/Alert.test.jsx.snap @@ -2,8 +2,7 @@ exports[`rendering renders correctly mandatory props only 1`] = `
+ `; diff --git a/src/lib/components/ui/Modal/__tests__/Modal.test.jsx b/src/lib/components/ui/Modal/__tests__/Modal.test.jsx index 4eda0b81..95d8c912 100644 --- a/src/lib/components/ui/Modal/__tests__/Modal.test.jsx +++ b/src/lib/components/ui/Modal/__tests__/Modal.test.jsx @@ -92,4 +92,3 @@ describe('functionality', () => { expect(spy.calledTwice).toEqual(true); }); }); - diff --git a/src/lib/theme.scss b/src/lib/theme.scss index 886385df..7efa39c3 100644 --- a/src/lib/theme.scss +++ b/src/lib/theme.scss @@ -146,7 +146,7 @@ // Alerts: common properties --rui-alert-border-width: var(--rui-border-width); --rui-alert-border-radius: var(--rui-border-radius); - --rui-alert-padding: var(--rui-offset-1); + --rui-alert-padding: var(--rui-offset-2); // Alerts: type: success --rui-alert-success-foreground-color: var(--rui-color-success);