diff --git a/amm-ui/qml/Main.qml b/amm-ui/qml/Main.qml index 52fa1ba..3ec1ce9 100644 --- a/amm-ui/qml/Main.qml +++ b/amm-ui/qml/Main.qml @@ -14,139 +14,160 @@ Item { { symbol: "TOK6", name: "Token 6", color: "#9b59b6", letter: "L", address: "0x1337000000000000000000000000000000000cafe", usdPrice: 0.42 } ] - // ── Theme ───────────────────────────────────────────────────────────────── - QtObject { - id: theme - property bool isDark: false - property var colors: isDark ? dark : light - - readonly property var light: ({ - background: "#f7f7f5", - cardBg: "#ffffff", - inputBg: "#f0f0ee", - panelBg: "#e8e8e4", - panelHoverBg: "#ddddd8", - textPrimary: "#111111", - textSecondary: "#777770", - textPlaceholder: "#bbbbb5", - border: Qt.rgba(0,0,0,0.08), - borderStrong: Qt.rgba(0,0,0,0.10), - divider: Qt.rgba(0,0,0,0.06), - ctaBg: "#111111", - ctaHoverBg: "#2a2a28", - selection: "#b5c4a5", - noTokenCircle: "#c8c8c4", - orb1: "#7a8c6a", - orb2: "#b5c4a5", - orb3: "#7a8c6a", - orb4: "#c8d4b8" - }) - - readonly property var dark: ({ - background: "#0d0d12", - cardBg: "#1a1a22", - inputBg: "#222230", - panelBg: "#2a2a38", - panelHoverBg: "#363650", - textPrimary: "#ffffff", - textSecondary: "#888899", - textPlaceholder: "#444455", - border: Qt.rgba(1,1,1,0.08), - borderStrong: Qt.rgba(1,1,1,0.10), - divider: Qt.rgba(1,1,1,0.06), - ctaBg: "#2d1530", - ctaHoverBg: "#3d1f40", - selection: "#4c1d4b", - noTokenCircle: "#444455", - orb1: "#627eea", - orb2: "#9b59b6", - orb3: "#fc72ff", - orb4: "#26a17b" - }) + // ── Navigation bar ──────────────────────────────────────────────────────── + // Pinned to the top; self-contained styling, unaffected by view themes. + NavBar { + id: navbar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + z: 100 } - // ── Root background ─────────────────────────────────────────────────────── - Rectangle { - anchors.fill: parent - color: theme.colors.background - Behavior on color { ColorAnimation { duration: 300 } } - - // Theme toggle - Rectangle { - anchors.top: parent.top - anchors.right: parent.right - anchors.margins: 16 - width: 44; height: 24; radius: 12 - color: theme.colors.panelBg - border.color: theme.colors.border - border.width: 1 - Text { - anchors.centerIn: parent - text: theme.isDark ? "☀" : "☾" - font.pixelSize: 13 - color: theme.colors.textSecondary - } - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: theme.isDark = !theme.isDark - } - } + // ── Content area (below the nav bar) ────────────────────────────────────── + Item { + anchors.top: navbar.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom - // Decorative orbs - Rectangle { x: -180; y: -120; width: 560; height: 560; radius: 280; color: theme.colors.orb1; opacity: 0.07 } - Rectangle { x: parent.width - 280; y: parent.height - 320; width: 480; height: 480; radius: 240; color: theme.colors.orb2; opacity: 0.09 } - Rectangle { x: parent.width - 200; y: -80; width: 380; height: 380; radius: 190; color: theme.colors.orb3; opacity: 0.05 } - Rectangle { x: 40; y: parent.height - 260; width: 320; height: 320; radius: 160; color: theme.colors.orb4; opacity: 0.08 } - - ColumnLayout { - anchors.centerIn: parent - spacing: 28 - - Text { - Layout.alignment: Qt.AlignHCenter - text: "Logos AMM" - color: theme.colors.textPrimary - font.pixelSize: 48 - font.weight: Font.Bold + // ── Trade view ──────────────────────────────────────────────────────── + Item { + anchors.fill: parent + visible: navbar.currentIndex === 0 + + // Trade view theme — scoped here, invisible to NavBar and LP view. + QtObject { + id: theme + property bool isDark: false + property var colors: isDark ? dark : light + + readonly property var light: ({ + background: "#f7f7f5", + cardBg: "#ffffff", + inputBg: "#f0f0ee", + panelBg: "#e8e8e4", + panelHoverBg: "#ddddd8", + textPrimary: "#111111", + textSecondary: "#777770", + textPlaceholder: "#bbbbb5", + border: Qt.rgba(0,0,0,0.08), + borderStrong: Qt.rgba(0,0,0,0.10), + divider: Qt.rgba(0,0,0,0.06), + ctaBg: "#111111", + ctaHoverBg: "#2a2a28", + selection: "#b5c4a5", + noTokenCircle: "#c8c8c4", + orb1: "#7a8c6a", + orb2: "#b5c4a5", + orb3: "#7a8c6a", + orb4: "#c8d4b8" + }) + + readonly property var dark: ({ + background: "#0d0d12", + cardBg: "#1a1a22", + inputBg: "#222230", + panelBg: "#2a2a38", + panelHoverBg: "#363650", + textPrimary: "#ffffff", + textSecondary: "#888899", + textPlaceholder: "#444455", + border: Qt.rgba(1,1,1,0.08), + borderStrong: Qt.rgba(1,1,1,0.10), + divider: Qt.rgba(1,1,1,0.06), + ctaBg: "#2d1530", + ctaHoverBg: "#3d1f40", + selection: "#4c1d4b", + noTokenCircle: "#444455", + orb1: "#627eea", + orb2: "#9b59b6", + orb3: "#fc72ff", + orb4: "#26a17b" + }) } - SwapCard { - id: swapCard - Layout.alignment: Qt.AlignHCenter - theme: theme - tokens: root.tokenData - width: Math.min(480, root.width - 32) + Rectangle { + anchors.fill: parent + color: theme.colors.background + Behavior on color { ColorAnimation { duration: 300 } } + + // Theme toggle + Rectangle { + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: 16 + width: 44; height: 24; radius: 12 + color: theme.colors.panelBg + border.color: theme.colors.border + border.width: 1 + Text { + anchors.centerIn: parent + text: theme.isDark ? "☀" : "☾" + font.pixelSize: 13 + color: theme.colors.textSecondary + } + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: theme.isDark = !theme.isDark + } + } - onRequestTokenSelect: function(side) { - tokenModal.targetSide = side - tokenModal.open() + // Decorative orbs + Rectangle { x: -180; y: -120; width: 560; height: 560; radius: 280; color: theme.colors.orb1; opacity: 0.07 } + Rectangle { x: parent.width - 280; y: parent.height - 320; width: 480; height: 480; radius: 240; color: theme.colors.orb2; opacity: 0.09 } + Rectangle { x: parent.width - 200; y: -80; width: 380; height: 380; radius: 190; color: theme.colors.orb3; opacity: 0.05 } + Rectangle { x: 40; y: parent.height - 260; width: 320; height: 320; radius: 160; color: theme.colors.orb4; opacity: 0.08 } + + ColumnLayout { + anchors.centerIn: parent + spacing: 28 + + SwapCard { + id: swapCard + Layout.alignment: Qt.AlignHCenter + theme: theme + tokens: root.tokenData + width: Math.min(480, root.width - 32) + + onRequestTokenSelect: function(side) { + tokenModal.targetSide = side + tokenModal.open() + } + } + + Text { + Layout.alignment: Qt.AlignHCenter + text: "Buy and sell crypto on LEZ." + textFormat: Text.RichText + color: theme.colors.textSecondary + font.pixelSize: 15 + horizontalAlignment: Text.AlignHCenter + } } - } - Text { - Layout.alignment: Qt.AlignHCenter - text: "Buy and sell crypto on LEZ." - textFormat: Text.RichText - color: theme.colors.textSecondary - font.pixelSize: 15 - horizontalAlignment: Text.AlignHCenter + TokenSelectorModal { + id: tokenModal + anchors.fill: parent + z: 10 + theme: theme + tokens: root.tokenData + + property string targetSide: "sell" + + onTokenSelected: function(tok) { + swapCard.setToken(targetSide, tok) + tokenModal.close() + } + } } } - TokenSelectorModal { - id: tokenModal + // ── Liquidity view (placeholder — replaced when LP branch merges) ───── + Item { anchors.fill: parent - z: 10 - theme: theme - tokens: root.tokenData - - property string targetSide: "sell" - - onTokenSelected: function(tok) { - swapCard.setToken(targetSide, tok) - tokenModal.close() - } + visible: navbar.currentIndex === 1 } } } diff --git a/amm-ui/qml/NavBar.qml b/amm-ui/qml/NavBar.qml new file mode 100644 index 0000000..4d8a105 --- /dev/null +++ b/amm-ui/qml/NavBar.qml @@ -0,0 +1,86 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + +// Self-contained navigation bar — styling is independent of any view's theme. +// Use currentIndex to read the active tab; tabChanged(index) fires on selection. +Item { + id: root + + property int currentIndex: 0 + readonly property var tabs: ["Trade", "Liquidity"] + + signal tabChanged(int index) + + implicitHeight: 56 + + Rectangle { + anchors.fill: parent + color: "#ffffff" + + // Bottom separator + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + height: 1 + color: Qt.rgba(0, 0, 0, 0.08) + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: 20 + anchors.rightMargin: 20 + spacing: 4 + + // App identity + Text { + text: "Logos AMM" + color: "#111111" + font.pixelSize: 17 + font.weight: Font.Bold + } + + Item { Layout.fillWidth: true } + + // Tab pills + Row { + spacing: 4 + + Repeater { + model: root.tabs + + delegate: Rectangle { + readonly property bool active: root.currentIndex === index + + height: 36 + width: tabLabel.implicitWidth + 28 + radius: 18 + color: active ? "#111111" : "transparent" + + Behavior on color { ColorAnimation { duration: 150 } } + + Text { + id: tabLabel + anchors.centerIn: parent + text: modelData + color: active ? "#ffffff" : "#666666" + font.pixelSize: 14 + font.weight: active ? Font.Medium : Font.Normal + + Behavior on color { ColorAnimation { duration: 150 } } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + root.currentIndex = index + root.tabChanged(index) + } + } + } + } + } + } + } +}