Charts
Bar charts
Bar charts short
Barchart empty
Bar charts with horizontal scroll
html
<div class="barChart">
<div class="barChart__graphContainer">
<ul class="barChart__graph">
<li class="barChart__group" data-info="january">
<p class="barChart__label">January</p>
<button class="barChart__toggle">Open January</button>
<ul class="barChart__bars">
<li class="barChart__bar pat--line bg--primary" data-value="74">
Value label: 74kwh
</li>
</ul>
</li>
<!-- More `barChart__group` li -->
</ul>
</div>
<div class="barChart__infos">
<div class="barChart__info" id="january">
<div class="barChart__infoContainer">
<p>January</p>
<p>Your HTML here</p>
</div>
</div>
<!-- More `barChart__info` divs -->
</div>
</div>Here is a more complex one, the only difference is the number of barChart__bar
html
<div class="barChart">
<div class="barChart__graphContainer">
<ul class="barChart__graph">
<li class="barChart__group" data-info="january">
<p class="barChart__label">January</p>
<button class="barChart__toggle">Open January</button>
<ul class="barChart__bars">
<li class="barChart__bar pat--line bg--primary" data-value="74">
Value label: 74kwh
</li>
<li class="barChart__bar pat--thinLine bg--primary" data-value="138">
Value label: 138kwh
</li>
<li class="barChart__bar pat--dot bg--accent" data-value="51">
Value label: 51kwh
</li>
<li class="barChart__bar pat--square bg--accent" data-value="94">
Value label: 94kwh
</li>
</ul>
</li>
<!-- More `barChart__group` li -->
</ul>
</div>
<div class="barChart__infos">
<div class="barChart__info" id="january">
<div class="barChart__infoContainer">
<p>January</p>
<p>Your HTML here</p>
</div>
</div>
<!-- More `barChart__info` divs -->
</div>
</div>Javascript
js
// $barChart is a '.barChart' html element
/**
* Get bars and all data related to it that can be usefull
*/
function buildBars() {
return Array.from($barChart.querySelectorAll('.barChart__bar')).map(
($bar) => {
return {
el: $bar,
value: Number($bar.dataset.value),
}
},
)
}
/**
* Get bar groups and all data related to it that can be usefull
*/
function buildBarGroups() {
const $barGroups = Array.from(
$barChart.querySelectorAll('.barChart__group'),
)
return $barGroups.map(($barGroup) => {
const info = $barGroup.dataset.info
? $barChart.querySelector(`#${$barGroup.dataset.info}`)
: null
return {
el: $barGroup,
toggle: $barGroup.querySelector('.barChart__toggle'),
info,
}
})
}
/**
* Get the bar with the highest value
*/
function getHighestBar(aBars) {
return aBars.reduce((oCarry, oBar) => {
if (oCarry) {
return oBar.value > oCarry.value ? oBar : oCarry
}
return oBar
}, null)
}
/**
* Get the percentage of a bar relative to another one
*/
function getRelativeHeight(oBar, oReference) {
return (oBar.value / oReference.value) * 100
}
/**
* Manage the component rendering by setting bars height as css variable
* to use it in out stylesheet
*/
function render(aBars) {
const oReference = getHighestBar(aBars)
aBars.forEach((oBar) => {
oBar.el.style.setProperty(
'--percentage',
`${getRelativeHeight(oBar, oReference)}%`,
)
})
}
/**
* Manage the modifier responsible of the white gradient on the right if the content overflows
*/
function manageOverflow($control) {
const $graph = $barChart.querySelector('.barChart__graph')
const $graphContainer = $barChart.querySelector(
'.barChart__graphContainer',
)
if ($graph.scrollWidth > $graphContainer.offsetWidth) {
if (!document.body.contains($control)) {
$graphContainer.insertAdjacentElement('afterbegin', $control)
}
} else {
$control.remove()
}
$barChart.classList.toggle(
'barChart--overflow',
$graph.scrollWidth > $graphContainer.offsetWidth,
)
}
/**
* Allows to open the corresponding info, uiseful to have a nice vertical transition
* Having no information is not a crashing
*/
function open(oCurrentBarGroup, aBarGroups) {
aBarGroups.forEach((oBarGroup) => {
oBarGroup.info?.classList.toggle(
CLASS_ACTIVE,
oCurrentBarGroup === oBarGroup,
)
oBarGroup.el.classList.toggle(
CLASS_ACTIVE,
oCurrentBarGroup === oBarGroup,
)
})
return oCurrentBarGroup
}
const aBarGroups = buildBarGroups()
const aBars = buildBars()
let oCurrentBar = open(aBarGroups[0], aBarGroups)
const $control = createElement({
tag: 'button',
innerHTML: 'Next',
attributes: {
class: 'barChart__control',
},
})
window.addEventListener('resize', () => manageOverflow($control))
aBarGroups.forEach((oBarGroup) =>
oBarGroup.toggle.addEventListener('click', () => {
oCurrentBar = open(oBarGroup, aBarGroups)
}),
)
$control?.addEventListener('click', (e) => {
e.preventDefault()
const iCurrentIndex = aBarGroups.findIndex(
(oBarGroup) => oBarGroup === oCurrentBar,
)
const iNextIndex =
iCurrentIndex + 1 >= aBarGroups.length ? 0 : iCurrentIndex + 1
oCurrentBar = open(aBarGroups[iNextIndex], aBarGroups)
aBarGroups[iNextIndex].el.scrollIntoView({
behaviour: 'smooth',
inline: 'center',
block: 'center',
})
})
manageOverflow($control)
render(aBars)Line chart
html
<div class="box">
<canvas class="dsChart" data-type="line"></canvas>
</div>js
new Chartjs.Chart($chart, {
data: {
labels: [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
datasets: [
// Default dataset example for temperatures.
{
label: 'Line chart',
type: 'line',
data: [
227, 411, 442, 483, 609, 562, 427, 735, 458,
205, 611, 688,
],
backgroundColor: (context) => {
if (context.chart.chartArea) {
const {
ctx,
chartArea: { top, bottom },
} = context.chart
const oGradienBg =
ctx.createLinearGradient(
0,
top,
0,
bottom,
)
oGradienBg.addColorStop(
0,
`${oColors.PRIMARY}40`,
)
oGradienBg.addColorStop(
1,
`${oColors.WHITE}FFF40`,
)
return oGradienBg
}
return [oColors.PRIMARY]
},
borderColor: [oColors.PRIMARY],
fill: true,
yAxisID: 'y',
tension: 0,
order: 1,
},
],
},
options: {
scales: {
y: {
grace: '5%',
ticks: {
callback: (value) => {
return `${value} kWh`
},
},
},
},
plugins: {
legend: {
position: 'bottom',
},
},
},
})doughnut chart
html
<div class="box">
<canvas class="dsChart" width="1" height="1" data-type="doughnut"></canvas>
</div>js
new Chartjs.Chart($chart, {
data: {
datasets: [
// Default dataset example for temperatures.
{
label: 'Doughnut chart',
type: $chart.dataset.type,
data: [227, 411, 688, 227, 411, 688],
backgroundColor: [
oColors.BLACK,
oColors.GREY,
oColors.GREY_OVERLAY,
oColors.GREY_LIGHT,
oColors.GREY_LIGHTER,
oColors.GREY_LIGHTEST,
],
},
],
},
options: {
responsive: true,
plugins: {
legend: {
display: false,
},
},
},
})