From 0b49915420eedf8e264e2dd168ea92dc5fe4182d Mon Sep 17 00:00:00 2001 From: neo Date: Sun, 21 Jun 2026 18:01:04 +0500 Subject: [PATCH] feat: Bloomberg Refresh 2024 table style for E-commerce tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added Bloomberg-style table with Follow buttons, ticker IDs, values, and change arrows - Two sections: Revenue by channel + Marketing metrics - SVG arrows (12x10) with fill=currentcolor for up/down/neutral states - Monospace typography for IDs, values, and change amounts - Responsive grid layout (desktop → tablet → mobile) - Follow button toggle with blue active state --- dashboard-mockup.html | 113 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/dashboard-mockup.html b/dashboard-mockup.html index 1b3e070..b030fce 100644 --- a/dashboard-mockup.html +++ b/dashboard-mockup.html @@ -196,15 +196,61 @@ body { .m-fill.yellow { background: var(--yellow); } .m-fill.blue { background: var(--accent); } +/* BLOOMBERG TABLE (E-commerce) */ +.b-table-section { display: none; } +.b-table-section.active { display: block; } +.b-table { + width: 100%; border-collapse: collapse; font-size: 13px; + background: #0e0e0e; border: 1px solid #1e1e1e; border-radius: 12px; overflow: hidden; +} +.b-table-header { display: grid; grid-template-columns: 44px 110px 1fr 120px 120px; padding: 10px 18px; border-bottom: 1px solid #1e1e1e; } +.b-th { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: #555; } +.b-th.right { text-align: right; } +.b-row { display: grid; grid-template-columns: 44px 110px 1fr 120px 120px; padding: 10px 18px; transition: background 0.15s; } +.b-row:hover { background: #131313; } +.b-row + .b-row { border-top: 1px solid #141414; } +.b-row:last-child { border-radius: 0 0 11px 11px; } +.b-follow { display: flex; align-items: center; justify-content: center; cursor: pointer; } +.b-follow-btn { + width: 22px; height: 22px; border: 1px solid #2a2a2a; border-radius: 6px; + background: transparent; color: #444; font-size: 12px; display: flex; + align-items: center; justify-content: center; transition: all 0.15s; +} +.b-follow-btn:hover { color: #f4f4f4; border-color: #444; background: #1a1a1a; } +.b-follow-btn.active { color: #0f6fff; border-color: #0f6fff; background: rgba(15,111,255,0.08); } +.b-id { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: #555; white-space: nowrap; } +.b-name { font-size: 13px; color: #d4d4d4; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.b-value { font-family: 'IBM Plex Mono', monospace; font-size: 14px; font-weight: 600; color: #f4f4f4; text-align: right; letter-spacing: -0.3px; } +.b-change { display: flex; align-items: center; justify-content: flex-end; gap: 4px; font-family: 'IBM Plex Mono', monospace; font-size: 12px; font-weight: 400; } +.b-change.up { color: #16a34a; } +.b-change.down { color: #e21d1d; } +.b-change.neutral { color: #3b82f6; } +.b-arrow { width: 12px; height: 10px; fill: currentColor; flex-shrink: 0; } +.b-section-title { + font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; + color: #444; padding: 20px 0 8px; margin-top: 8px; border-top: 1px solid #1a1a1a; +} +.b-section-title:first-child { border-top: none; margin-top: 0; } +.b-table-caption { + display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; +} +.b-table-caption-title { font-size: 14px; font-weight: 600; color: #d4d4d4; } +.b-table-caption-sub { font-size: 12px; color: #555; } + /* RESPONSIVE */ @media(max-width: 1024px) { .kpi-grid { grid-template-columns: repeat(3, 1fr); } + .b-table-header, .b-row { grid-template-columns: 44px 80px 1fr 90px 90px; } } @media(max-width: 640px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); } .topbar { padding: 0 16px; } .page-header, .tabs-section, .charts-wrap { padding-left: 16px; padding-right: 16px; } .tab-btn { padding: 12px 14px; font-size: 13px; } + .b-table-header, .b-row { grid-template-columns: 36px 70px 1fr 70px 70px; padding: 8px 12px; } + .b-name { font-size: 12px; } + .b-value { font-size: 12px; } + .b-change { font-size: 11px; } } @@ -233,6 +279,26 @@ body {
+ +
+
+
+ Каналы и метрики + Обновлено только что +
+
Выручка по каналам
+ + + +
IDКаналВыручкаИзменение
+
Маркетинговые метрики
+ + + +
IDМетрикаЗначениеИзменение
+
+
+
@@ -388,6 +454,53 @@ function seg(key) { }).join(''); requestAnimationFrame(() => g.querySelectorAll('.kpi').forEach(c => c.classList.add('visible'))); + // Bloomberg table — channels + marketing + const arrowUp = ''; + const arrowDown = ''; + const arrowNeutral = ''; + function changeCell(val, t) { + const cls = t === 'up' ? 'up' : t === 'down' ? 'down' : 'neutral'; + const arrow = t === 'up' ? arrowUp : t === 'down' ? arrowDown : arrowNeutral; + const sign = t === 'up' ? '+' : t === 'down' ? '−' : '±'; + return `
${arrow} ${sign}${val}
`; + } + const channels = [ + { id:'SEO:CH', name:'SEO-трафик', value:'1.2М ₽', change:'18', t:'up' }, + { id:'PPC:CH', name:'Контекстная реклама', value:'980К ₽', change:'12', t:'up' }, + { id:'SMM:CH', name:'Соцсети', value:'640К ₽', change:'−3', t:'down' }, + { id:'EMAIL:CH',name:'Email-рассылки', value:'420К ₽', change:'8', t:'up' }, + { id:'ORG:CH', name:'Органический', value:'380К ₽', change:'2', t:'up' }, + { id:'REF:CH', name:'Реферальный', value:'156К ₽', change:'24', t:'up' }, + { id:'AFF:CH', name:'Партнёрские', value:'98К ₽', change:'−12', t:'down' }, + ]; + const marketing = [ + { id:'CAC', name:'Стоимость клиента', value:'680 ₽', change:'8', t:'down' }, + { id:'AOV', name:'Ср. чек', value:'4 820 ₽', change:'3', t:'up' }, + { id:'CVR', name:'Конверсия', value:'3.8%', change:'0.5', t:'up' }, + { id:'CLV', name:'Пож. ценность', value:'12 400 ₽', change:'18', t:'up' }, + { id:'ROAS', name:'ROAS', value:'4.2×', change:'15', t:'up' }, + { id:'Bounce', name:'Показ. отказов', value:'32%', change:'1', t:'down' }, + ]; + + function renderTable(body, data) { + body.innerHTML = data.map((d, i) => ` + + + ${d.id} + ${d.name} + ${d.value} + ${changeCell(d.change, d.t)} + `).join(''); + // Follow toggle + body.querySelectorAll('.b-follow-btn').forEach(btn => { + btn.addEventListener('click', () => btn.classList.toggle('active')); + }); + } + const tbody1 = document.querySelector('#b-table-channels tbody'); + const tbody2 = document.querySelector('#b-table-marketing tbody'); + if (tbody1) renderTable(tbody1, channels); + if (tbody2) renderTable(tbody2, marketing); + // Sparkline charts const sparkColors = []; s.kpis.forEach(d => { sparkColors.push(d.t === 'up' ? '#22c55e' : d.t === 'down' ? '#ef4444' : '#3b82f6'); });