diff --git a/src/components/App/App.css b/src/components/App/App.css index 9ec9d69..c08bdb7 100644 --- a/src/components/App/App.css +++ b/src/components/App/App.css @@ -19,3 +19,9 @@ #root * { font-family: BundesSans, sans-serif; } + +.theme { + display: flex; + flex-direction: column; + height: 100%; +} diff --git a/src/components/App/App.js b/src/components/App/App.js index 237edff..8c2b8a4 100644 --- a/src/components/App/App.js +++ b/src/components/App/App.js @@ -9,7 +9,11 @@ import { defaultChatbotComponents, initialQuestionParameter, } from "../../helpers/constants"; -import { supportedServiceNames, supportedServices } from "../../services"; +import { + supportedServiceNames, + supportedServices, + supportedThemes, +} from "../../services"; class App extends Component { constructor(props) { @@ -31,6 +35,7 @@ class App extends Component { defaultBackendType in supportedServiceNames ? defaultBackendType : supportedServiceNames[0], + currentTheme: "default", }; this.texts = textsHelper.getTexts(); @@ -39,6 +44,7 @@ class App extends Component { this.setBackendUrl = this.setBackendUrl.bind(this); this.setComponents = this.setComponents.bind(this); this.setBackendType = this.setBackendType.bind(this); + this.setTheme = this.setTheme.bind(this); // TODO: Add back in once we move on from the MVP // this.toggleComponent = this.toggleComponent.bind(this); } @@ -150,6 +156,14 @@ class App extends Component { ); } + setTheme(themeName) { + if (!supportedThemes.includes(themeName)) return; + + this.setState({ + currentTheme: themeName, + }); + } + setComponents(components) { // is array and only contains strings, if it has elements // TODO: Edit string check back once we move on from the MVP @@ -234,16 +248,18 @@ class App extends Component { ].replace("{{url}}", this.state.backendUrl) : this.texts["default-responses"]["initial-message"]["is-not-configured"]; return ( - <> +
- +
); } } diff --git a/src/components/Button/Button.css b/src/components/Button/Button.css index c8d4bfd..ad65e50 100644 --- a/src/components/Button/Button.css +++ b/src/components/Button/Button.css @@ -1,13 +1,28 @@ .button { - background-color: var(--bright-blue); - box-shadow: 0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12); - border-radius: 7px; min-height: fit-content; min-width: fit-content; cursor: pointer; } +.default.theme .button { + background-color: var(--bright-blue); + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12); + border-radius: 7px; +} + +.itzbund.theme .button { + background-color: var(--green); + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12); + color: var(--light-white); + border: none; + border-radius: 2px; + padding: 0.5rem; +} + .button:focus { - box-shadow: 0 6px 2px -4px rgba(0,0,0,.4),0 4px 4px 0 rgba(0,0,0,.28),0 2px 10px 0 rgba(0,0,0,.24); + box-shadow: 0 6px 2px -4px rgba(0, 0, 0, 0.4), 0 4px 4px 0 rgba(0, 0, 0, 0.28), + 0 2px 10px 0 rgba(0, 0, 0, 0.24); outline: none; -} \ No newline at end of file +} diff --git a/src/components/Button/Button.jsx b/src/components/Button/Button.jsx index 9faeee7..6925f46 100644 --- a/src/components/Button/Button.jsx +++ b/src/components/Button/Button.jsx @@ -3,7 +3,7 @@ import "./Button.css"; /** * @description a styled, robust button component - * + * * @property {string} className A string containing all complementary classes. This will not replace the button's classes, it will only add to them. * @property {object} style An object containing the "inline" style of the object * @property {function} onClick The function that should be called when the button is clicked diff --git a/src/components/Message/Message.css b/src/components/Message/Message.css index d566570..c067e12 100644 --- a/src/components/Message/Message.css +++ b/src/components/Message/Message.css @@ -11,26 +11,60 @@ flex-direction: row; } -.messageContainer.reply .messageDataContainer { +.default.theme .messageContainer.reply .messageDataContainer { background-color: var(--bright-teal); } +.itzbund.theme .messageContainer.reply .messageDataContainer { + background-color: var(--gray-100); +} + +.itzbund.theme .messageContainer:not(.reply) .messageDataContainer, +.itzbund.theme .messageContainer:not(.reply) .messageDataContainer * { + background-color: var(--green); + color: var(--light-white); +} + .messageDataContainer { height: fit-content; border-radius: 14px; - box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), - 0 1px 5px 0 rgba(0, 0, 0, 0.12); display: flex; flex-direction: column; overflow-x: scroll; } +.default.theme .messageDataContainer { + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12); + color: var(--light-white); +} + +.itzbund.theme .messageDataContainer { + background-color: var(--gray-100); + box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.2); + color: var(--light-black); + border: none; + border-radius: 2px; + position: relative; +} + .messageContainer.reply .messageDataContainer:focus { - background-color: var(--dark-teal); outline: none; } -.messageContainer:not(.reply) .messageDataContainer:focus { +.default.theme + .messageContainer.messageContainer.reply + .messageDataContainer:focus { + background-color: var(--dark-teal); +} + +.itzbund.theme + .messageContainer.messageContainer.reply + .messageDataContainer:focus { + background-color: var(--gray-100); +} + +.default.theme .messageContainer:not(.reply) .messageDataContainer:focus { background-color: rgb(230, 230, 230); } @@ -52,11 +86,20 @@ text-align: right; } -.messageContainer.reply .messageTimeSent { - color: white; +.itzbund.theme .messageContainer.reply .messageTimeSent { + color: var(--light-black); outline: none; } -.messageContainer:not(.reply) .messageTimeSent { +.default .messageContainer.reply .messageTimeSent { + color: var(--light-white); + outline: none; +} + +.itzbund.theme .messageContainer:not(.reply) .messageTimeSent { + color: var(--light-white); +} + +.default.theme .messageContainer:not(.reply) .messageTimeSent { color: var(--bright-teal); } diff --git a/src/components/MessageInput/MessageInput.css b/src/components/MessageInput/MessageInput.css index 30023f8..e17504c 100644 --- a/src/components/MessageInput/MessageInput.css +++ b/src/components/MessageInput/MessageInput.css @@ -2,23 +2,50 @@ #messageInput { position: relative; - height: 150px; + height: 100px; width: 100%; - border-top: 2px solid #f0f0f0; + border-top: 2px solid var(--gray-100); + box-shadow: 0px -2px 8px 0px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0px -2px 8px 0px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0px -2px 8px 0px rgba(0, 0, 0, 0.2); display: flex; flex-wrap: nowrap; +} + +.default.theme #messageInput { align-items: stretch; } +.itzbund.theme #messageInput { + background-color: var(--gray-300); + align-items: center; + justify-content: center; +} + +.itzbund.theme #messageInput > * { + margin-inline: 0.5rem; +} + #inputTextBox { position: relative; - font-size: x-large; - width: 90%; resize: none; - display: inline-block; padding: 1ex; } +.default.theme #inputTextBox { + width: 90%; + font-size: x-large; + display: inline-block; +} + +.itzbund.theme #inputTextBox { + background-color: var(--light-white); + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.25); + width: 33%; + font-size: 1em; + height: 25%; +} + #inputTextBox::placeholder { color: rgb(100, 100, 100); } @@ -65,7 +92,7 @@ } #loadingBar.visible::before { - content: ''; + content: ""; position: relative; display: block; left: 0%; @@ -75,4 +102,4 @@ height: 7.5px; background-color: #aa2941; animation: load 1.75s infinite; -} \ No newline at end of file +} diff --git a/src/components/MessageInput/MessageInput.jsx b/src/components/MessageInput/MessageInput.jsx index 5c83648..9dd7fc6 100644 --- a/src/components/MessageInput/MessageInput.jsx +++ b/src/components/MessageInput/MessageInput.jsx @@ -4,7 +4,7 @@ import "./MessageInput.css"; import { textsHelper } from "../../helpers"; /** - * + * * @property {function} sendMessage The callback to be called using the message input's text * @property {boolean} isSending Value determining if loading bar is displayed */ @@ -27,7 +27,7 @@ export default class MessageInput extends Component { this.listenerId = textsHelper.addListener(() => { this.texts = textsHelper.getTexts(); this.forceUpdate(); - }) + }); } componentWillUnmount() { @@ -42,7 +42,8 @@ export default class MessageInput extends Component { } inputTextChange(changeEvent) { - if (changeEvent.target.value !== "\n") this.setState({ query: changeEvent.target.value }); + if (changeEvent.target.value !== "\n") + this.setState({ query: changeEvent.target.value }); } inputKeyPress(keyPressEvent) { @@ -77,7 +78,7 @@ export default class MessageInput extends Component { height: "40px", marginRight: "10px", }} - className={"light-gray black-text vertical-center right-side"} + className={"vertical-center right-side"} /> diff --git a/src/components/PageHeader/PageHeader.css b/src/components/PageHeader/PageHeader.css index 603c84e..09ac2b1 100644 --- a/src/components/PageHeader/PageHeader.css +++ b/src/components/PageHeader/PageHeader.css @@ -1,107 +1,140 @@ #header { - position: relative; - display: flex; - flex-wrap: nowrap; - height: 75px; - width: 100%; - z-index: 1; - background-color: var(--dark-teal); + position: relative; + display: flex; + flex-wrap: nowrap; + height: 75px; + width: 100%; + z-index: 1; } -#header > *{ - flex-grow: 1; - flex-shrink: 2; +.default.theme #header { + background-color: var(--dark-teal); +} + +.itzbund.theme #header { + background-color: var(--white); + border-bottom: 1px solid rgba(0, 0, 0, 0.15); + box-shadow: 0px 10px 17px 0px rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0px 10px 17px 0px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0px 10px 17px 0px rgba(0, 0, 0, 0.1); +} + +.itzbund.theme #header * { + color: var(--light-green); + font-weight: bold; +} + +.default.theme #header * { + color: var(--light-white); +} + +#header > * { + flex-grow: 1; + flex-shrink: 2; } .questionsToggle { - position: relative; - min-width: 80px; - height: 100%; + position: relative; + min-width: 80px; + height: 100%; } .pageTitle { - position: relative; - flex-grow: 15 !important; - height: 100%; + position: relative; + flex-grow: 15 !important; + height: 100%; } .pageTitle > a { - font-size: x-large; - width: 100%; - text-align: center; - text-decoration: none; + font-size: x-large; + width: 100%; + text-align: center; + text-decoration: none; } @media screen and (max-width: 339px) { - .clickableIcon { - width: 80px !important; - } + .clickableIcon { + width: 80px !important; + } } @media screen and (max-width: 319px) { - .questionsToggle, .pageTitle > a { - min-width: 60px; - font-size: small; - } - - .clickableIcon { - width: 70px !important; - } + .questionsToggle, + .pageTitle > a { + min-width: 60px; + font-size: small; + } + + .clickableIcon { + width: 70px !important; + } } @media screen and (max-width: 269px) { - .questionsToggle, .pageTitle > a { - min-width: 50px; - font-size: x-small; - } - - .clickableIcon { - width: 60px !important; - } + .questionsToggle, + .pageTitle > a { + min-width: 50px; + font-size: x-small; + } + + .clickableIcon { + width: 60px !important; + } } @media screen and (max-width: 229px) { - .questionsToggle, .pageTitle > a { - min-width: 40px; - font-size: xx-small; - } + .questionsToggle, + .pageTitle > a { + min-width: 40px; + font-size: xx-small; + } + + .clickableIcon { + width: 50px !important; + } +} - .clickableIcon { - width: 50px !important; - } +.default.theme .questionsToggle:hover { + background-color: var(--bright-teal); + cursor: pointer; } -.questionsToggle:hover { - background-color: var(--bright-teal); - cursor: pointer; +.itzbund.theme .questionsToggle:hover * { + text-decoration: underline; + cursor: pointer; } -.questionsToggle:focus { - outline: none; - background-color: var(--bright-teal); - text-decoration: underline 1px #000 solid; +.default.theme .questionsToggle:focus { + outline: none; + background-color: var(--bright-teal); + text-decoration: underline 1px #000 solid; +} + +.itzbund.theme .questionsToggle:focus { + outline: none; + text-decoration: underline; } .exampleQuestion { - width: 100%; - display: flex; - flex-wrap: wrap; - justify-content: space-evenly; - word-break: normal; + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + word-break: normal; } .exampleQuestion div:not(.button) { - width: 80%; + width: 80%; } #imprint.contentContainer { - display: initial; + display: initial; } .exampleQuestion { - padding-bottom: 0.5rem; + padding-bottom: 0.5rem; } .questionSectionTitle { - font-size: x-large; - padding-bottom: 1rem; -} \ No newline at end of file + font-size: x-large; + padding-bottom: 1rem; +} diff --git a/src/components/PageHeader/PageHeader.jsx b/src/components/PageHeader/PageHeader.jsx index 0fc3571..798d64b 100644 --- a/src/components/PageHeader/PageHeader.jsx +++ b/src/components/PageHeader/PageHeader.jsx @@ -7,7 +7,9 @@ import { } from ".."; import { textsHelper } from "../../helpers"; import flag_icon from "../share/imgs/flag_icon.webp"; +import settings_icon_black from "../share/imgs/settings_icon_black.svg"; import settings_icon_white from "../share/imgs/settings_icon_white.svg"; +import info_icon_black from "../share/imgs/info_icon_black.svg"; import info_icon_white from "../share/imgs/info_icon_white.svg"; import "./PageHeader.css"; import { chatbotFrontendUrl } from "../../helpers/constants"; @@ -63,7 +65,11 @@ export default class PageHeader extends Component {
+ Select backend type:{" "}
+
+ Select design theme:{" "} + +
a { - color: rgb(0, 0, 0); + color: var(--dark-black); } .white-text > a, .white-text > a:visited { - color: rgb(197, 197, 197); + color: var(--dark-white); } diff --git a/src/services/index.js b/src/services/index.js index 6754935..7216f9a 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -9,3 +9,5 @@ export const supportedServices = { export const supportedServiceNames = Object.keys(supportedServices).filter( (name) => Object.prototype.hasOwnProperty.call(supportedServices, name) ); + +export const supportedThemes = ["default", "itzbund"]; diff --git a/src/texts/de/texts.json b/src/texts/de/texts.json index d82fa77..a933760 100644 --- a/src/texts/de/texts.json +++ b/src/texts/de/texts.json @@ -63,5 +63,5 @@ "admin-panel-url": "Liste der Komponenten", "select-service-type": "Wählen Sie die Art des Services aus, den Sie nutzen möchten: " }, - "credits": "Diese Anwendung wurde am Fachbereich Informatik und Sprachen der Hochschule Anhalt unter der Leitung von Prof. Dr. Andreas Both und mit der Unterstützung von Paul Heinze durch Jonas Wunsch entwickelt. Für diese Anwendung gilt die Apache 2.0 Lizenz." + "credits": "Diese Anwendung wurde am Fachbereich Informatik und Sprachen der Hochschule Anhalt unter der Leitung von Prof. Dr. Andreas Both und mit der Unterstützung von Paul Heinze durch Jonas Wunsch entwickelt. Für diese Anwendung gilt die Apache 2.0 Lizenz." } diff --git a/src/texts/en/texts.json b/src/texts/en/texts.json index 4e98b39..6d2d3c0 100644 --- a/src/texts/en/texts.json +++ b/src/texts/en/texts.json @@ -63,5 +63,5 @@ "admin-panel-url": "List of components", "select-service-type": "Select the type of service you want to use: " }, - "credits": "This application has been developed by Jonas Wunsch at the Department of Computer Science and Languages of the Anhalt University of Applied Sciences under the direction of Prof. Dr. Andreas Both and with help from Paul Heinze. The Apache 2.0 license applies to this project." + "credits": "This application has been developed by Jonas Wunsch at the Department of Computer Science and Languages of the Anhalt University of Applied Sciences under the direction of Prof. Dr. Andreas Both and with help from Paul Heinze. The Apache 2.0 license applies to this project." }