From 68545056d8668d3222bb81780ad484c079d2a069 Mon Sep 17 00:00:00 2001
From: Hassan Abouelela <hassan@hassanamr.com>
Date: Fri, 1 Jul 2022 00:10:01 +0400
Subject: Allow More Customization In Error Message

Add transitions to the error message component, and allow more
flexibility by allowing the caller to specify the inner component of the
message.

Signed-off-by: Hassan Abouelela <hassan@hassanamr.com>
---
 src/components/ErrorMessage.tsx | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

(limited to 'src/components/ErrorMessage.tsx')

diff --git a/src/components/ErrorMessage.tsx b/src/components/ErrorMessage.tsx
index 650100d..cbadcdc 100644
--- a/src/components/ErrorMessage.tsx
+++ b/src/components/ErrorMessage.tsx
@@ -1,10 +1,12 @@
 /** @jsx jsx */
 import { jsx, css } from "@emotion/react";
 import colors from "../colors";
+import {selectable} from "../commonStyles";
 
 interface ErrorMessageProps {
     show: boolean,
-    message: string
+    message: string,
+    innerElement?: JSX.Element,
 }
 
 export default function ErrorMessage(props: ErrorMessageProps): JSX.Element | null {
@@ -13,12 +15,21 @@ export default function ErrorMessage(props: ErrorMessageProps): JSX.Element | nu
       font-size: 1.15rem;
       line-height: 1.1rem;
       margin: 1rem 0 0;
+
       visibility: ${props.show ? "visible" : "hidden"};
+      opacity: ${props.show ? 1 : 0};
+      transition: opacity 200ms, visibility 200ms;
+    `;
+
+    // These styles are not applied when inner element is explicitly set
+    const floatingStyles = css`
       position: absolute;
       z-index: -1;
     `;
 
     return (
-        <p css={styles}>{props.message}</p>
+        <div tabIndex={-1} css={[styles, selectable, props.innerElement ? null : floatingStyles]}>
+            {props.innerElement ? props.innerElement : props.message}
+        </div>
     );
 }
-- 
cgit v1.2.3


From acb7df25f258701722ee56b087e272b7118fe8ac Mon Sep 17 00:00:00 2001
From: Hassan Abouelela <hassan@hassanamr.com>
Date: Fri, 1 Jul 2022 01:17:19 +0400
Subject: Style Changes

Signed-off-by: Hassan Abouelela <hassan@hassanamr.com>
---
 src/api/question.ts             | 4 ++--
 src/components/ErrorMessage.tsx | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/components/ErrorMessage.tsx')

diff --git a/src/api/question.ts b/src/api/question.ts
index 3561055..a9a4d4a 100644
--- a/src/api/question.ts
+++ b/src/api/question.ts
@@ -17,7 +17,7 @@ export interface Question {
     required: boolean
 }
 
-type unittestError = {
+type UnittestError = {
     question_id: string,
     question_index: number,
     return_code: number,
@@ -27,5 +27,5 @@ type unittestError = {
 
 export interface UnittestFailure {
     error: string,
-    test_results: unittestError[],
+    test_results: UnittestError[],
 }
diff --git a/src/components/ErrorMessage.tsx b/src/components/ErrorMessage.tsx
index cbadcdc..e6078ff 100644
--- a/src/components/ErrorMessage.tsx
+++ b/src/components/ErrorMessage.tsx
@@ -1,5 +1,5 @@
 /** @jsx jsx */
-import { jsx, css } from "@emotion/react";
+import {jsx, css} from "@emotion/react";
 import colors from "../colors";
 import {selectable} from "../commonStyles";
 
-- 
cgit v1.2.3


From 9696f5269ddbc1ba090830f84cb17ac6624c777f Mon Sep 17 00:00:00 2001
From: Hassan Abouelela <hassan@hassanamr.com>
Date: Fri, 1 Jul 2022 13:41:48 +0400
Subject: Improve ErrorMessage Interface

Unify the string and element types on the interface to clarify they are
mutually exclusive.

Signed-off-by: Hassan Abouelela <hassan@hassanamr.com>
---
 src/components/ErrorMessage.tsx | 11 ++++++-----
 src/components/Question.tsx     |  4 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

(limited to 'src/components/ErrorMessage.tsx')

diff --git a/src/components/ErrorMessage.tsx b/src/components/ErrorMessage.tsx
index e6078ff..6151603 100644
--- a/src/components/ErrorMessage.tsx
+++ b/src/components/ErrorMessage.tsx
@@ -5,8 +5,7 @@ import {selectable} from "../commonStyles";
 
 interface ErrorMessageProps {
     show: boolean,
-    message: string,
-    innerElement?: JSX.Element,
+    content: string | JSX.Element,
 }
 
 export default function ErrorMessage(props: ErrorMessageProps): JSX.Element | null {
@@ -21,15 +20,17 @@ export default function ErrorMessage(props: ErrorMessageProps): JSX.Element | nu
       transition: opacity 200ms, visibility 200ms;
     `;
 
-    // These styles are not applied when inner element is explicitly set
+    // These styles are not applied when content is an element;
     const floatingStyles = css`
       position: absolute;
       z-index: -1;
     `;
 
+    const isString = typeof props.content === "string";
+
     return (
-        <div tabIndex={-1} css={[styles, selectable, props.innerElement ? null : floatingStyles]}>
-            {props.innerElement ? props.innerElement : props.message}
+        <div tabIndex={-1} css={[styles, selectable, isString ? floatingStyles : null]}>
+            {props.content}
         </div>
     );
 }
diff --git a/src/components/Question.tsx b/src/components/Question.tsx
index b42ea09..d4883ec 100644
--- a/src/components/Question.tsx
+++ b/src/components/Question.tsx
@@ -252,7 +252,7 @@ class RenderedQuestion extends React.Component<QuestionProp> {
         }
 
         const element = <div css={css`white-space: pre-wrap; word-wrap: break-word;`}>{inner}</div>;
-        return <ErrorMessage show={!valid} message={""} innerElement={element}/>;
+        return <ErrorMessage show={!valid} content={element}/>;
     }
 
     render(): JSX.Element {
@@ -323,7 +323,7 @@ class RenderedQuestion extends React.Component<QuestionProp> {
                 // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                 // @ts-ignore
                 const message: string = this.props.public_state.get("error");
-                error = <ErrorMessage show={!valid} message={message}/>;
+                error = <ErrorMessage show={!valid} content={message}/>;
             }
 
             return <div ref={this.props.scroll_ref}>
-- 
cgit v1.2.3

