diff --git a/ui/StatusQ/sandbox/main.qml b/ui/StatusQ/sandbox/main.qml
index 44eccf89cb..11103d40bf 100644
--- a/ui/StatusQ/sandbox/main.qml
+++ b/ui/StatusQ/sandbox/main.qml
@@ -197,6 +197,11 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
+ StatusNavigationListItem {
+ title: "StatusTextArea"
+ selected: viewLoader.source.toString().includes(title)
+ onClicked: mainPageView.page(title);
+ }
StatusNavigationListItem {
title: "StatusSelect"
selected: viewLoader.source.toString().includes(title)
diff --git a/ui/StatusQ/sandbox/pages/StatusTextAreaPage.qml b/ui/StatusQ/sandbox/pages/StatusTextAreaPage.qml
new file mode 100644
index 0000000000..1d556aa245
--- /dev/null
+++ b/ui/StatusQ/sandbox/pages/StatusTextAreaPage.qml
@@ -0,0 +1,61 @@
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+import StatusQ.Controls 0.1
+
+Column {
+ id: root
+
+ spacing: 8
+
+ Component.onCompleted: {
+ focusedTextArea.forceActiveFocus()
+ }
+
+ StatusTextArea {
+ id: focusedTextArea
+ width: parent.width
+ placeholderText: "Initially focused text area"
+ KeyNavigation.tab: unfocusedTextArea
+ }
+
+ StatusTextArea {
+ id: unfocusedTextArea
+ width: parent.width
+ placeholderText: "Unfocused text area (hover me to see the color change)"
+ KeyNavigation.tab: invalidTextArea
+ }
+
+ StatusTextArea {
+ id: invalidTextArea
+ width: parent.width
+ valid: false
+ placeholderText: "Invalid text area, should display red border"
+ KeyNavigation.tab: longTextArea
+ }
+
+ StatusScrollView {
+ padding: 0 // use our own (StatusTextArea) padding
+ width: parent.width
+ height: 120
+ TextArea.flickable: longTextArea
+ StatusTextArea {
+ id: longTextArea
+ text: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer imperdiet lectus quis justo. Sed vel lectus. \
+ Donec odio tempus molestie, porttitor ut, iaculis quis, sem. Morbi scelerisque luctus velit. Nunc auctor. Nullam at \
+ arcu a est sollicitudin euismod. Cras elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, \
+ per inceptos hymenaeos. Fusce aliquam vestibulum ipsum. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. \
+ Nullam sit amet magna in magna gravida vehicula. Cras pede libero, dapibus nec, pretium sit amet, tempor quis. Nullam faucibus \
+ mi quis velit. Nam sed tellus id magna elementum tincidunt. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, \
+ eget facilisis enim ipsum id lacus. Maecenas aliquet accumsan leo. Aliquam erat volutpat."
+ KeyNavigation.tab: focusedTextArea
+ }
+ }
+
+ StatusTextArea {
+ enabled: false
+ placeholderText: "Disabled text area"
+ }
+}
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml b/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml
new file mode 100644
index 0000000000..caed2277bb
--- /dev/null
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusTextArea.qml
@@ -0,0 +1,111 @@
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+
+import StatusQ.Core.Theme 0.1
+
+/*!
+ \qmltype StatusTextArea
+ \inherits Item
+ \inqmlmodule StatusQ.Controls
+ \since StatusQ.Controls 0.1
+ \brief Displays a multi line text input component.
+ Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-controls2-textarea.html}{QQC.TextArea}.
+
+ The \c StatusTextArea displays a styled TextArea for users to type multiple lines of text.
+ For example:
+
+ \qml
+ StatusTextArea {
+ width: parent.width
+ placeholderText: qsTr("Search")
+ }
+ \endqml
+
+ Note: if you want to alter the TAB key behavior, just override it like this:
+ \qml
+ StatusTextArea {
+ width: parent.width
+ KeyNavigation.tab: otherItemThatAcceptsFocus
+ }
+ \endqml
+
+ Note 2: if scrolling is required, just wrap the StatusTextArea inside a StatusScrollView, e.g.:
+ \qml
+ StatusScrollView {
+ padding: 0 // use our own (StatusTextArea) padding
+ width: parent.width
+ height: 120
+ TextArea.flickable: longTextArea
+ StatusTextArea {
+ id: longTextArea
+ text: "Very\nlong\ntext\nwith\nmany\nlinebreaks"
+ }
+ }
+ \endqml
+
+ For a list of components available see StatusQ.
+*/
+
+TextArea {
+ id: root
+
+ /*!
+ \qmlproperty bool StatusTextArea::valid
+ This property sets the valid state. Default value is true.
+ */
+ property bool valid: true
+
+ implicitWidth: 448 // by design
+ implicitHeight: 108
+
+ leftPadding: 16
+ rightPadding: 16
+ topPadding: 10
+ bottomPadding: 10
+
+ color: Theme.palette.directColor1
+ selectedTextColor: color
+ selectionColor: Theme.palette.primaryColor2
+ placeholderTextColor: root.enabled ? Theme.palette.baseColor1 : Theme.palette.directColor9
+
+ font {
+ family: Theme.palette.baseFont.name
+ pixelSize: 15
+ }
+
+ selectByMouse: true
+ wrapMode: TextEdit.WordWrap
+
+ activeFocusOnTab: enabled
+ KeyNavigation.priority: KeyNavigation.BeforeItem
+
+ background: Rectangle {
+ radius: 8
+ color: root.enabled ? Theme.palette.baseColor2 : Theme.palette.baseColor4
+ border.width: 1
+ border.color: {
+ if (!root.valid)
+ return Theme.palette.dangerColor1
+ if (root.activeFocus)
+ return Theme.palette.primaryColor1
+ if (root.hovered)
+ return Theme.palette.primaryColor2
+ return "transparent"
+ }
+ }
+
+ cursorDelegate: Rectangle {
+ color: Theme.palette.primaryColor1
+ implicitWidth: 2
+ implicitHeight: 22
+ radius: 1
+ visible: root.cursorVisible
+
+ SequentialAnimation on visible {
+ loops: Animation.Infinite
+ running: root.cursorVisible
+ PropertyAnimation { to: false; duration: 600 }
+ PropertyAnimation { to: true; duration: 600 }
+ }
+ }
+}
diff --git a/ui/StatusQ/src/StatusQ/Controls/qmldir b/ui/StatusQ/src/StatusQ/Controls/qmldir
index cd7c15aee7..02abc18361 100644
--- a/ui/StatusQ/src/StatusQ/Controls/qmldir
+++ b/ui/StatusQ/src/StatusQ/Controls/qmldir
@@ -50,3 +50,4 @@ StatusIconTextButton 0.1 StatusIconTextButton.qml
StatusScrollBar 0.1 StatusScrollBar.qml
StatusComboBox 0.1 StatusComboBox.qml
StatusItemDelegate 0.1 StatusItemDelegate.qml
+StatusTextArea 0.1 StatusTextArea.qml
diff --git a/ui/StatusQ/src/StatusQ/Layout/StatusAppTwoPanelLayout.qml b/ui/StatusQ/src/StatusQ/Layout/StatusAppTwoPanelLayout.qml
index ab4a29f224..4998850b8f 100644
--- a/ui/StatusQ/src/StatusQ/Layout/StatusAppTwoPanelLayout.qml
+++ b/ui/StatusQ/src/StatusQ/Layout/StatusAppTwoPanelLayout.qml
@@ -5,7 +5,7 @@ import QtQuick.Controls 2.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
-Item {
+FocusScope {
id: statusAppTwoPanelLayout
implicitWidth: 822
diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc
index 9ed1db556d..6a66590f8e 100644
--- a/ui/StatusQ/src/statusq.qrc
+++ b/ui/StatusQ/src/statusq.qrc
@@ -112,6 +112,7 @@
StatusQ/Controls/StatusToolTip.qml
StatusQ/Controls/StatusWalletColorButton.qml
StatusQ/Controls/StatusWalletColorSelect.qml
+ StatusQ/Controls/StatusTextArea.qml
StatusQ/Core/Backpressure/Backpressure.qml
StatusQ/Core/Backpressure/LICENSE
StatusQ/Core/Backpressure/qmldir