import QtQuick import ".." as M Item { id: root required property string buffer required property string state implicitHeight: 48 implicitWidth: 280 // Background pill Rectangle { anchors.fill: parent color: { if (root.state === "fail" || root.state === "error") return Qt.rgba(M.Theme.base08.r, M.Theme.base08.g, M.Theme.base08.b, 0.15); if (root.state === "busy") return Qt.rgba(M.Theme.base0D.r, M.Theme.base0D.g, M.Theme.base0D.b, 0.1); return M.Theme.base02; } radius: height / 2 border.color: { if (root.state === "fail" || root.state === "error") return M.Theme.base08; if (root.state === "busy") return M.Theme.base0D; return M.Theme.base03; } border.width: 1 Behavior on color { ColorAnimation { duration: 200 } } Behavior on border.color { ColorAnimation { duration: 200 } } } // Placeholder text Text { anchors.centerIn: parent text: { if (root.state === "busy") return "Authenticating..."; if (root.state === "max") return "Too many attempts"; return "Enter password"; } color: M.Theme.base04 font.pixelSize: M.Theme.fontSize font.family: M.Theme.fontFamily opacity: root.buffer.length === 0 ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 150 } } } // Password dots Row { anchors.centerIn: parent spacing: 6 Repeater { model: root.buffer.length delegate: Rectangle { required property int index width: 10 height: 10 radius: 5 color: M.Theme.base05 scale: 0 opacity: 0 Component.onCompleted: { scale = 1; opacity = 1; } Behavior on scale { NumberAnimation { duration: 120 easing.type: Easing.OutBack } } Behavior on opacity { NumberAnimation { duration: 100 } } } } } }