diff --git a/pkg/miniapp/static/index.html b/pkg/miniapp/static/index.html index f6cfdfe1b..8a276429d 100644 --- a/pkg/miniapp/static/index.html +++ b/pkg/miniapp/static/index.html @@ -17,6 +17,15 @@ --done: #34c759; --current: var(--btn); --pending-phase: var(--hint); + /* Liquid Glass */ + --glass-bg: rgba(255, 255, 255, 0.55); + --glass-border: rgba(0, 0, 0, 0.08); + --glass-border-interactive: rgba(0, 0, 0, 0.15); + --glass-shadow: rgba(0, 0, 0, 0.06); + --glass-divider: rgba(0, 0, 0, 0.06); + --tab-bar-bg: rgba(255, 255, 255, 0.72); + --tab-track-bg: rgba(0, 0, 0, 0.06); + --tab-pill-bg: rgba(255, 255, 255, 0.9); } @media (prefers-color-scheme: dark) { @@ -28,6 +37,15 @@ --btn: var(--tg-theme-button-color, #5ac8fa); --btn-text: var(--tg-theme-button-text-color, #ffffff); --secondary-bg: var(--tg-theme-secondary-bg-color, #2c2c2e); + /* Liquid Glass — dark */ + --glass-bg: rgba(255, 255, 255, 0.08); + --glass-border: rgba(255, 255, 255, 0.1); + --glass-border-interactive: rgba(255, 255, 255, 0.22); + --glass-shadow: rgba(0, 0, 0, 0.2); + --glass-divider: rgba(255, 255, 255, 0.08); + --tab-bar-bg: rgba(28, 28, 30, 0.72); + --tab-track-bg: rgba(255, 255, 255, 0.1); + --tab-pill-bg: rgba(255, 255, 255, 0.16); } } @@ -43,15 +61,40 @@ .tabs { display: flex; - background: var(--secondary-bg); position: sticky; top: 0; z-index: 10; + padding: 8px 12px; + background: var(--tab-bar-bg); + -webkit-backdrop-filter: saturate(180%) blur(20px); + backdrop-filter: saturate(180%) blur(20px); + } + + .tabs-inner { + display: flex; + position: relative; + width: 100%; + background: var(--tab-track-bg); + border-radius: 10px; + padding: 2px; + } + + .tab-indicator { + position: absolute; + top: 2px; + bottom: 2px; + left: 2px; + width: calc(25% - 2px); + border-radius: 8px; + background: var(--tab-pill-bg); + box-shadow: 0 0.5px 2px rgba(0,0,0,0.12), 0 0.5px 1px rgba(0,0,0,0.08); + transition: transform 0.38s cubic-bezier(0.25, 1, 0.5, 1); + z-index: 0; } .tab { flex: 1; - padding: 12px 4px; + padding: 7px 4px; text-align: center; font-size: 13px; font-weight: 500; @@ -59,36 +102,43 @@ border: none; background: none; cursor: pointer; - border-bottom: 2px solid transparent; - transition: all 0.2s; + transition: color 0.25s ease; + position: relative; + z-index: 1; + -webkit-tap-highlight-color: transparent; } .tab.active { - color: var(--btn); - border-bottom-color: var(--btn); + color: var(--text); + font-weight: 600; } .panel { display: none; padding: 16px; } .panel.active { display: block; } .card { - background: var(--secondary-bg); - border-radius: 12px; - padding: 14px; + background: var(--glass-bg); + border: 1px solid var(--glass-border); + border-radius: 16px; + padding: 16px; margin-bottom: 12px; + box-shadow: 0 1px 3px var(--glass-shadow); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); } .card-title { - font-size: 13px; + font-size: 12px; color: var(--hint); margin-bottom: 8px; text-transform: uppercase; - letter-spacing: 0.5px; + letter-spacing: 0.6px; + font-weight: 600; } .card-value { - font-size: 20px; - font-weight: 600; + font-size: 22px; + font-weight: 700; } /* Plan - phase/step list */ @@ -99,15 +149,15 @@ .phase-header { display: flex; align-items: center; - gap: 8px; - padding: 10px 0 6px; + gap: 10px; + padding: 10px 0 8px; font-weight: 600; - font-size: 14px; + font-size: 15px; } .phase-indicator { - width: 22px; - height: 22px; + width: 24px; + height: 24px; border-radius: 50%; display: flex; align-items: center; @@ -120,39 +170,45 @@ .phase-indicator.done { background: var(--done); } .phase-indicator.current { background: var(--current); } - .phase-indicator.pending { background: var(--pending-phase); } + .phase-indicator.pending { background: var(--glass-divider); color: var(--hint); } .phase-title { flex: 1; } .phase-progress { font-size: 12px; color: var(--hint); - font-weight: 400; + font-weight: 500; } .step { display: flex; align-items: flex-start; gap: 10px; - padding: 10px 12px 10px 30px; - margin-bottom: 4px; - border-radius: 8px; + padding: 12px 14px 12px 34px; + margin-bottom: 6px; + border-radius: 12px; cursor: pointer; - transition: all 0.15s; + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), box-shadow 0.2s; + -webkit-tap-highlight-color: transparent; } .step:active { transform: scale(0.97); } - .step:not(.step-done) { background: var(--secondary-bg); } + .step:not(.step-done) { + background: var(--glass-bg); + border: 1px solid var(--glass-border-interactive); + box-shadow: 0 0.5px 2px var(--glass-shadow); + } .step-check { - width: 20px; - height: 20px; - border-radius: 6px; + width: 22px; + height: 22px; + border-radius: 50%; border: 2px solid var(--hint); flex-shrink: 0; display: flex; align-items: center; justify-content: center; - margin-top: 1px; + margin-top: 0; + transition: all 0.2s; } .step-check.done { @@ -183,24 +239,29 @@ /* Skills */ .skill-item { - background: linear-gradient(to bottom, var(--bg), var(--secondary-bg)); - border-radius: 12px; + background: var(--glass-bg); + border-radius: 16px; padding: 14px 14px 14px 16px; margin-bottom: 10px; cursor: pointer; - transition: all 0.12s; - border: 1px solid var(--hint); + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), box-shadow 0.2s, border-color 0.2s; + border: 1px solid var(--glass-border-interactive); display: flex; align-items: center; gap: 12px; - box-shadow: 0 2px 4px rgba(0,0,0,0.08), 0 1px 0 rgba(255,255,255,0.06) inset; + box-shadow: 0 1px 3px var(--glass-shadow); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); + -webkit-tap-highlight-color: transparent; } .skill-item:active { - transform: scale(0.98) translateY(1px); - box-shadow: 0 0 2px rgba(0,0,0,0.06); + transform: scale(0.98); + } + .skill-item.selected { + border-color: var(--btn); + box-shadow: 0 2px 8px var(--glass-shadow); } - .skill-item.selected { border-color: var(--btn); box-shadow: 0 2px 6px rgba(0,0,0,0.12); } .skill-body { flex: 1; min-width: 0; } @@ -219,18 +280,19 @@ .skill-source { display: inline-block; font-size: 11px; - padding: 2px 8px; - border-radius: 10px; - background: var(--btn); - color: var(--btn-text); + padding: 3px 10px; + border-radius: 20px; + background: var(--tab-track-bg); + color: var(--hint); margin-top: 6px; + font-weight: 500; } .skill-arrow { color: var(--hint); font-size: 22px; flex-shrink: 0; - transition: color 0.15s; + transition: color 0.2s; } .skill-item.selected .skill-arrow { color: var(--btn); } @@ -238,13 +300,13 @@ .stat-row { display: flex; justify-content: space-between; - padding: 10px 0; - border-bottom: 1px solid var(--secondary-bg); + padding: 11px 0; + border-bottom: 1px solid var(--glass-divider); } .stat-row:last-child { border-bottom: none; } - .stat-label { color: var(--hint); } - .stat-value { font-weight: 600; } + .stat-label { color: var(--hint); font-size: 14px; } + .stat-value { font-weight: 600; font-size: 14px; } /* Send bar */ .send-bar { @@ -252,22 +314,27 @@ bottom: 0; left: 0; right: 0; - background: var(--bg); + background: var(--tab-bar-bg); + -webkit-backdrop-filter: saturate(180%) blur(20px); + backdrop-filter: saturate(180%) blur(20px); padding: 12px 16px; display: flex; gap: 8px; - border-top: 1px solid var(--secondary-bg); + border-top: 1px solid var(--glass-divider); } .send-input { flex: 1; - padding: 10px 14px; + padding: 10px 16px; border-radius: 20px; - border: 1px solid var(--hint); - background: var(--bg); + border: 1px solid var(--glass-border-interactive); + background: var(--glass-bg); color: var(--text); font-size: 14px; outline: none; + -webkit-backdrop-filter: blur(8px); + backdrop-filter: blur(8px); + transition: border-color 0.2s; } .send-input:focus { border-color: var(--btn); } @@ -281,23 +348,26 @@ font-size: 14px; font-weight: 600; cursor: pointer; + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), background 0.15s; + -webkit-tap-highlight-color: transparent; } - .send-btn:active { opacity: 0.8; } + .send-btn:active { transform: scale(0.95); } .send-btn:disabled { opacity: 0.5; } - .send-btn.sent { background: var(--done); transition: background 0.15s; } + .send-btn.sent { background: var(--done); } .empty-state { text-align: center; color: var(--hint); - padding: 40px 20px; - font-size: 14px; + padding: 48px 20px; + font-size: 15px; } .loading { text-align: center; color: var(--hint); - padding: 40px 20px; + padding: 48px 20px; + font-size: 15px; } .cmd-tiles { @@ -308,60 +378,65 @@ .cmd-tile { padding: 16px 14px; - border-radius: 12px; - border: 1px solid var(--hint); - background: linear-gradient(to bottom, var(--bg), var(--secondary-bg)); + border-radius: 14px; + border: 1px solid var(--glass-border-interactive); + background: var(--glass-bg); color: var(--text); font-size: 15px; font-weight: 600; cursor: pointer; - transition: all 0.12s; + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), background 0.15s; text-align: center; - box-shadow: 0 2px 4px rgba(0,0,0,0.1), 0 1px 0 rgba(255,255,255,0.06) inset; + box-shadow: 0 1px 3px var(--glass-shadow); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); + -webkit-tap-highlight-color: transparent; } .cmd-tile:active { - transform: scale(0.96) translateY(1px); - box-shadow: 0 0 2px rgba(0,0,0,0.08); - background: var(--secondary-bg); + transform: scale(0.96); } .cmd-tile.sent { background: var(--btn); color: var(--btn-text); border-color: var(--btn); - box-shadow: 0 2px 4px rgba(0,0,0,0.15); - transition: all 0.15s; } .refresh-btn { display: block; width: 100%; padding: 12px 16px; - border-radius: 12px; - border: 1px solid var(--hint); - background: linear-gradient(to bottom, var(--bg), var(--secondary-bg)); + border-radius: 14px; + border: 1px solid var(--glass-border-interactive); + background: var(--glass-bg); color: var(--text); font-size: 14px; + font-weight: 500; cursor: pointer; - margin-top: 8px; - transition: all 0.12s; - box-shadow: 0 2px 4px rgba(0,0,0,0.08); + margin-top: 12px; + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1); + box-shadow: 0 1px 3px var(--glass-shadow); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); + -webkit-tap-highlight-color: transparent; } .refresh-btn:active { - transform: scale(0.98) translateY(1px); - box-shadow: 0 0 2px rgba(0,0,0,0.06); + transform: scale(0.98); }
- - - - +
+
+ + + + +
@@ -412,12 +487,20 @@ let initData = tg.initData || ''; let selectedSkill = null; // Tab switching — always re-fetch data on tab switch -document.querySelectorAll('.tab').forEach(tab => { +const tabs = document.querySelectorAll('.tab'); +const tabIndicator = document.querySelector('.tab-indicator'); + +function moveIndicator(index) { + tabIndicator.style.transform = 'translateX(' + (index * 100) + '%)'; +} + +tabs.forEach((tab, index) => { tab.addEventListener('click', () => { - document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); + tabs.forEach(t => t.classList.remove('active')); document.querySelectorAll('.panel').forEach(p => p.classList.remove('active')); tab.classList.add('active'); document.getElementById(tab.dataset.panel).classList.add('active'); + moveIndicator(index); document.getElementById('send-bar').style.display = tab.dataset.panel === 'skills' && selectedSkill ? 'flex' : 'none';