Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
frame_source
Python Playground
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Fork
account_circle
Login
settings
Settings
expand_more
Editor font
14
px
A
A
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
left_panel_close
AI Assistant
dashboard
All
HTML
CSS
JS
visibility
Preview
bolt
Live Preview
terminal
JS Console
<!DOCTYPE html> <html> <head> <title>Donut chart using ChartJS</title> </head> <body> <!-- Start your code here --> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <div class="dashboard"> <div class="header"> <div> <div class="eyebrow">DATA VISUALIZATION</div> <h1>Distribution</h1> </div> <select id="dataSelect"> <option value="traffic">Traffic</option> <option value="devices">Devices</option> <option value="revenue">Revenue</option> </select> </div> <div class="charts"> <div class="chart-card"> <div class="card-header"> <div> <span>OVERVIEW</span> <h2 id="chartTitle">Traffic sources</h2> </div> <div class="period"> 2026 </div> </div> <div class="chart-wrap"> <canvas id="donutChart"></canvas> <div class="center-label"> <strong id="centerValue">100%</strong> <span id="centerText">TOTAL</span> </div> </div> <div class="legend" id="legend"> </div> </div> <div class="chart-card second"> <div class="card-header"> <div> <span>BREAKDOWN</span> <h2>Composition</h2> </div> </div> <div class="mini-list" id="miniList"></div> </div> </div> </div> <!-- End your code here --> </body> </html>
* { box-sizing: border-box; } html, body { width: 100%; height: 100%; margin: 0; } body { font-family: Arial, Helvetica, sans-serif; background: #f3f1eb; color: #151515; } /* ========================================= DASHBOARD ========================================= */ .dashboard { width: min(1050px, calc(100% - 40px)); margin: 60px auto; } /* ========================================= HEADER ========================================= */ .header { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 25px; } .eyebrow { font-size: 9px; letter-spacing: 2.5px; color: #8b877d; margin-bottom: 7px; } h1 { margin: 0; font-size: 42px; letter-spacing: -2px; } select { min-width: 150px; padding: 10px 13px; background: white; border: 1px solid #bbb7af; border-radius: 7px; font-size: 11px; color: #222; outline: none; } /* ========================================= CHARTS ========================================= */ .charts { display: grid; grid-template-columns: 1.35fr 1fr; gap: 18px; } /* ========================================= CARD ========================================= */ .chart-card { position: relative; background: white; border: 1px solid #d9d5cc; border-radius: 18px; padding: 24px; min-height: 480px; } .chart-card.second { min-height: auto; } /* ========================================= HEADER ========================================= */ .card-header { display: flex; justify-content: space-between; align-items: flex-start; } .card-header span { display: block; font-size: 8px; letter-spacing: 1.5px; color: #9a958b; } .card-header h2 { margin: 7px 0 0; font-size: 20px; letter-spacing: -0.5px; } .period { padding: 6px 9px; background: #f2f0ea; border-radius: 6px; font-size: 9px; color: #777269; } /* ========================================= DONUT ========================================= */ .chart-wrap { position: relative; width: 300px; height: 300px; margin: 35px auto 10px; } .chart-wrap canvas { width: 100% !important; height: 100% !important; } .center-label { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); text-align: center; pointer-events: none; } .center-label strong { display: block; font-size: 38px; letter-spacing: -2px; } .center-label span { display: block; margin-top: 3px; font-size: 8px; letter-spacing: 2px; color: #9a958b; } /* ========================================= LEGEND ========================================= */ .legend { display: flex; justify-content: center; flex-wrap: wrap; gap: 16px; margin-top: 15px; } .legend-item { display: flex; align-items: center; gap: 7px; font-size: 10px; color: #6f6b64; } .legend-dot { width: 8px; height: 8px; border-radius: 50%; } /* ========================================= MINI LIST ========================================= */ .mini-list { margin-top: 24px; } .mini-row { display: grid; grid-template-columns: 1fr auto; gap: 15px; padding: 16px 0; border-bottom: 1px solid #e5e1d9; } .mini-row:last-child { border-bottom: none; } .mini-name { font-size: 12px; font-weight: 600; } .mini-bar { margin-top: 8px; width: 100%; height: 5px; background: #ece9e2; border-radius: 10px; overflow: hidden; } .mini-bar-fill { height: 100%; border-radius: 10px; transition: width 0.6s ease; } .mini-value { align-self: start; font-size: 13px; font-weight: 600; } /* ========================================= MOBILE ========================================= */ @media (max-width: 800px) { .charts { grid-template-columns: 1fr; } .chart-wrap { width: 260px; height: 260px; } .header { align-items: flex-start; flex-direction: column; gap: 15px; } }
/* ========================================= DATA ========================================= */ const datasets = { traffic: { title: "Traffic sources", labels: [ "Organic", "Direct", "Social", "Referral" ], values: [ 42, 28, 18, 12 ], center: "100%" }, devices: { title: "Device usage", labels: [ "Desktop", "Mobile", "Tablet", "Other" ], values: [ 51, 34, 11, 4 ], center: "100%" }, revenue: { title: "Revenue mix", labels: [ "Subscriptions", "Services", "Licensing", "Other" ], values: [ 48, 25, 17, 10 ], center: "100%" } }; /* ========================================= COLORS ========================================= */ const colors = [ "#111111", "#74706a", "#b8b2a8", "#ddd8cf" ]; /* ========================================= ELEMENTS ========================================= */ const canvas = document.getElementById( "donutChart" ); const title = document.getElementById( "chartTitle" ); const centerValue = document.getElementById( "centerValue" ); const legend = document.getElementById( "legend" ); const miniList = document.getElementById( "miniList" ); const select = document.getElementById( "dataSelect" ); /* ========================================= CHART INSTANCE ========================================= */ let chart = null; /* ========================================= CENTER TEXT PLUGIN ========================================= */ const centerTextPlugin = { id: "centerText", beforeDraw(chart) { const ctx = chart.ctx; const meta = chart.getDatasetMeta(0); /* Make sure the donut has been created. */ if ( !meta || !meta.data || !meta.data.length ) { return; } /* Get the center of the donut. */ const x = meta.data[0].x; const y = meta.data[0].y; ctx.save(); /* ===================================== REMOVE ALL SHADOWS ===================================== */ ctx.shadowColor = "transparent"; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; /* Text alignment */ ctx.textAlign = "center"; ctx.textBaseline = "middle"; /* ===================================== MAIN VALUE ===================================== */ ctx.font = "bold 34px Arial"; ctx.fillStyle = "#151515"; ctx.fillText( centerValue.textContent, x, y - 6 ); /* ===================================== TOTAL LABEL ===================================== */ ctx.font = "8px Arial"; ctx.fillStyle = "#9a958b"; ctx.fillText( "TOTAL", x, y + 25 ); ctx.restore(); } }; /* ========================================= RENDER CHART ========================================= */ function render(key) { const data = datasets[key]; /* Update heading. */ title.textContent = data.title; /* Update center value. */ centerValue.textContent = data.center; /* Destroy previous chart. */ if (chart) { chart.destroy(); chart = null; } /* ===================================== CREATE CHART ===================================== */ chart = new Chart( canvas, { type: "doughnut", data: { labels: data.labels, datasets: [ { data: data.values, backgroundColor: colors, /* White separators between segments. */ borderColor: "#ffffff", borderWidth: 3, /* Makes segment expand slightly on hover. */ hoverOffset: 12, /* Small visual spacing between segments. */ spacing: 2 } ] }, options: { responsive: true, maintainAspectRatio: false, /* Size of donut hole. */ cutout: "69%", animation: { duration: 900, easing: "easeOutQuart" }, plugins: { /* We create our own legend below the chart. */ legend: { display: false }, /* Tooltip */ tooltip: { backgroundColor: "#151515", titleColor: "#ffffff", bodyColor: "#ffffff", padding: 12, cornerRadius: 8, displayColors: true } } }, plugins: [ centerTextPlugin ] } ); /* ===================================== CUSTOM LEGEND ===================================== */ legend.innerHTML = data.labels .map( function( label, index ) { return ` <div class="legend-item" > <span class="legend-dot" style=" background-color: ${colors[index]}; " ></span> <span> ${label} </span> </div> `; } ) .join(""); /* ===================================== DETAIL LIST ===================================== */ miniList.innerHTML = data.labels .map( function( label, index ) { const value = data.values[index]; return ` <div class="mini-row" > <div> <div class="mini-name" > ${label} </div> <div class="mini-bar" > <div class="mini-bar-fill" style=" width: ${value}%; background-color: ${colors[index]}; " ></div> </div> </div> <div class="mini-value" > ${value}% </div> </div> `; } ) .join(""); } /* ========================================= DATA SELECTOR ========================================= */ select.addEventListener( "change", function() { render( this.value ); } ); /* ========================================= INITIAL STATE ========================================= */ render( "traffic" );
terminal
JavaScript Console
Preview
Clear
close
›
Run