// SPDX-License-Identifier: GPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of nymea-app-energy-overlay. * * nymea-app-energy-overlay is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nymea-app-energy-overlay is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with nymea-app-energy-overlay. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Nymea as N import "qrc:/ui/components" Item { id: root property string title: "" property string iconSource: "" property string iconSourceActive: "" property int animationSpeed: 250 property bool animationEnabled: false property bool activeTab: false readonly property real expandedWidth: iconContainer.width + textWidth readonly property real textWidth: textLabel.implicitWidth + 2 * N.Style.margins onActiveTabChanged: { if (activeTab) { print("Active tab:", title, "implicit width", root.expandedWidth) } } Rectangle { id: background anchors.centerIn: parent height: parent.height width: activeTab ? contentRow.width : height radius: height / 2 color: activeTab ? N.Style.accentColor : "transparent" } Row { id: contentRow anchors.centerIn: parent height: parent.height spacing: 0 property color color: N.Style.foregroundColor Item { id: iconContainer width: N.Style.iconSize + (root.height - N.Style.iconSize) / 2 height: root.height anchors.verticalCenter: parent.verticalCenter visible: root.iconSource.length > 0 ColorIcon { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right width: N.Style.iconSize height: width name: root.activeTab ? root.iconSourceActive : root.iconSource color: root.activeTab ? contentRow.color : N.Style.accentColor } } Item { id: textContainer height: root.height anchors.verticalCenter: parent.verticalCenter width: activeTab ? textWidth : 0 opacity: 0 Label { id: textLabel anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin: N.Style.margins / 2 text: root.title color: contentRow.color } } } states: [ State { name: "active" when: root.activeTab == true PropertyChanges { target: textContainer width: textWidth } PropertyChanges { target: textContainer opacity: 1 } }, State { name: "inactive" when: root.activeTab == false PropertyChanges { target: textContainer width: 0 } PropertyChanges { target: textContainer opacity: 0 } } ] transitions: [ Transition { from: "active" to: "inactive" // No transition, just do it... }, Transition { from: "inactive" to: "active" SequentialAnimation { NumberAnimation { properties: "width" duration: root.animationSpeed easing.type: Easing.Linear } SmoothedAnimation { properties: "opacity" duration: root.animationSpeed } } } ] }