diff --git a/app/components/App.jsx b/app/components/App.jsx
index b6670505..bc41149a 100644
--- a/app/components/App.jsx
+++ b/app/components/App.jsx
@@ -49,33 +49,43 @@ export default class App extends Component {
});
this.props.controller.on(Events.DECRYPTION_FAILED, (state) => {
- const message = [
- 'We were unable to decrypt the document. Either the secret has not',
- 'been supplied or it is invalid.',
- 'We have redirected you to a new document.'
- ].join(' ');
+ const message = {
+ content: [
+ 'We were unable to decrypt the document. Either the secret has not',
+ 'been supplied or it is invalid.',
+ 'We have redirected you to a new document.'
+ ].join(' '),
+ type: 'error'
+ }
this.loadAndRedirect(state.document, '/', message);
});
this.props.controller.on(Events.DOCUMENT_NOT_FOUND, (state) => {
- const message = [
- 'We could not find the document you were trying to load, so we have',
- 'redirected you to a new document.'
- ].join(' ');
+ const message = {
+ content: [
+ 'We could not find the document you were trying to load, so we have',
+ 'redirected you to a new document.'
+ ].join(' '),
+ type: 'error'
+ };
this.loadAndRedirect(state.document, '/', message);
});
this.props.controller.on(Events.CONFLICT, (state) => {
- const message = [
- Snap!,
- ' The document you were working on has been updated by a third,',
- ' and you are now working on a fork. You can still find the original',
- ' (and updated) document: ',
- here,
- '.'
- ];
+ const message = {
+ content: (
+
+ Snap!
+ The document you were working on has been updated by a third,
+ and you are now working on a fork. You can still find the original
+ (and updated) document:
+ here.
+
+ ),
+ type: 'warning'
+ };
this.loadAndRedirect(
state.fork.document,
@@ -87,10 +97,13 @@ export default class App extends Component {
this.props.controller.on(Events.UPDATE_WITHOUT_CONFLICT, (state) => {
this.setState({
document: state.document,
- message: [
- 'We have updated the document you are viewing to its latest revision.',
- 'Happy reading/working!'
- ].join(' ')
+ message: {
+ content: [
+ 'We have updated the document you are viewing to its latest revision.',
+ 'Happy reading/working!'
+ ].join(' '),
+ type: 'info'
+ }
});
});
@@ -124,7 +137,7 @@ export default class App extends Component {
return (
-
+
- {this.props.message}
+
+
{this.props.message.content}
);
}
@@ -15,3 +17,7 @@ export default class MessageBox extends Component {
return null;
}
}
+
+MessageBox.propTypes = {
+ message: object.isRequired
+}
diff --git a/app/components/__tests__/MessageBox-test.js b/app/components/__tests__/MessageBox-test.js
index 50b53227..de7766e5 100644
--- a/app/components/__tests__/MessageBox-test.js
+++ b/app/components/__tests__/MessageBox-test.js
@@ -17,9 +17,23 @@ describe('', () => {
});
it('renders a message', () => {
- const wrapper = shallow();
+ const message = {
+ content: 'hello.'
+ };
+ const wrapper = shallow();
expect(wrapper.find('.message-box')).to.have.length(1);
expect(wrapper.text()).to.equal('hello.');
});
+
+it('renders a typed message', () => {
+ const message = {
+ content: 'hello.',
+ type: 'info'
+ };
+ const wrapper = shallow();
+
+ expect(wrapper.find('.message-box.info')).to.have.length(1);
+ expect(wrapper.text()).to.equal('hello.');
+ });
});
diff --git a/app/scss/_settings.scss b/app/scss/_settings.scss
index edbce433..05cbcb74 100644
--- a/app/scss/_settings.scss
+++ b/app/scss/_settings.scss
@@ -17,7 +17,7 @@ $foundation-palette: (
secondary: $mercury,
success: #3adb76,
warning: #ffae00,
- alert: #ec5840,
+ alert: #ec5840
);
// Global
@@ -27,6 +27,7 @@ $global-radius: 5px;
$common-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
$body-font-family: 'LatoLatinLight', $common-font-family;
$header-font-family: 'LatoLatin', $common-font-family;
+$callout-font-family: $header-font-family;
// Typography
$code-font-family: Consolas, 'Liberation Mono', Courier, monospace;
@@ -37,6 +38,9 @@ $print-transparent-backgrounds: false;
// Callout
$callout-radius: 0;
$callout-margin: 0;
+$callout-background-fade: 20%;
+$callout-font-color: $alabaster;
+$callout-border: 0 none none;
/* -- Monod settings -- */
$footer-font-family: 'LatoLatin', $common-font-family;
diff --git a/app/scss/components/_message_box.scss b/app/scss/components/_message_box.scss
index 71392ddf..42286c44 100644
--- a/app/scss/components/_message_box.scss
+++ b/app/scss/components/_message_box.scss
@@ -1,9 +1,51 @@
+/*
+ * MessageBox component
+ */
+$message-box-height: 65px;
+
.message-box {
- @include callout-base;
- background-color: lighten($warning-color, 40%);
+ @include callout;
+ position: fixed;
+ width: 100%;
+ z-index: 10000;
+ font-size: 1.2rem;
+ font-family: $callout-font-family;
+ min-height: $message-box-height;
+
+ // We support up to 10 simultaneous notifications
+ @for $i from 1 through 10 {
+ &:nth-child(#{$i}) {
+ margin-top: #{($i - 2) * $message-box-height};
+ }
+ }
+
+ &.warning {
+ @include callout-style($warning-color);
+ color: darken($warning-color, 15%);
+ border-bottom: 3px solid $warning-color;
+ }
+
+ &.error {
+ @include callout-style($alert-color);
+ border-bottom: 3px solid $alert-color;
+ }
+
+ &.success {
+ @include callout-style($success-color);
+ border-bottom: 3px solid $success-color;
+ }
+
+ &.info {
+ @include callout-style(lighten($primary-color, 5%));
+ border-bottom: 3px solid $primary-color;
+ }
+
+ a {
+ color: inherit;
+ text-decoration: underline;
- p {
- margin-bottom: 0 !important;
- margin-right: 1rem;
- }
+ &:hover {
+ background-color: rgba(#fff, 0.2);
+ }
+ }
}