Last active
November 16, 2021 13:52
-
-
Save mithicher/d6e416c5e087f4a0c66e282299479cf9 to your computer and use it in GitHub Desktop.
PureCSS Horizontal Bar Chart Laravel Blade Component with AlpineJS and TailwindCSS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{-- Usage | |
<x-purecss-horizontal-bar-chart | |
bar-chart-id="horizontalbar" | |
bar-color="bg-gradient-to-r from-indigo-300 to-purple-400" | |
:chart-data='[ | |
[ | |
"label" => "Team A", | |
"value" => 25, | |
], | |
[ | |
"label" => "Team B", | |
"value" => 10, | |
], | |
[ | |
"label" => "Team C", | |
"value" => 60, | |
], | |
[ | |
"label" => "Team D", | |
"value" => 80, | |
], | |
[ | |
"label" => "Team E", | |
"value" => 35, | |
], | |
[ | |
"label" => "Team F", | |
"value" => 45, | |
], | |
[ | |
"label" => "Team G", | |
"value" => 95, | |
], | |
]' | |
> | |
<x-slot name="columnData"> | |
<div x-text="`${data.value} wins`"></div> | |
</x-slot> | |
<x-slot name="labelData"> | |
<div class="text-right text-sm leading-none font-medium font-mono" x-text="`For ${data.label}`"></div> | |
</x-slot> | |
<x-slot name="tooltip"> | |
<div class="bg-gray-800 shadow rounded-md p-1.5 text-white absolute mx-2 leading-none text-xs z-30 -mt-20" x-cloak x-text="`${data.label}: ${data.value} wins`"></div> | |
</x-slot> | |
</x-purecss-horizontal-bar-chart> | |
--}} | |
@props([ | |
'barColor' => 'bg-blue-600 hover:bg-blue-400', | |
'barChartId' => md5(Str::random(8)), | |
'chartData' => [] | |
]) | |
<div x-data="{ | |
chartId: '{{ $barChartId }}', | |
chartData: {{ collect($chartData) }}, | |
get totalSumOfChartData() { | |
if (this.chartData.length > 0 || Object.keys(this.chartData).length > 0) { | |
return this.chartData.map(item => item.value).reduce((acc, value) => value + acc); | |
} | |
return 0; | |
} | |
}" x-cloak> | |
<div x-show="chartData.length > 0" class="flex w-full"> | |
<!-- Bar Chart --> | |
<div class="flex-1"> | |
<div class="relative flex flex-col space-y-4" id="{{ $barChartId }}"> | |
<template x-for="(data, dataIndex) in chartData" :key="dataIndex"> | |
<div class="relative w-full flex items-center h-10"> | |
{{-- Labels --}} | |
<div class="absolute z-30 left-0 top-0 flex h-full px-4 items-center font-medium text-gray-700 text-sm leading-none md:relative md:text-right md:justify-end"> | |
@isset($labelData) | |
{{ $labelData }} | |
@else | |
<div x-text="data.label" class="w-32"></div> | |
@endisset | |
</div> | |
<div class="relative h-full flex flex-1 w-full items-center"> | |
{{-- Bar --}} | |
<div | |
class="bg-gray-100 relative transition ease-in duration-200 relative h-full flex-1 w-full" | |
x-on:mouseenter="document.getElementById(chartId + dataIndex).className = 'block w-full h-full'" | |
x-on:mouseleave="document.getElementById(chartId + dataIndex).className = 'hidden'"> | |
<div | |
:style="`width: ${(data.value/totalSumOfChartData*100).toFixed(2)}%`" | |
class="transition ease-in duration-200 relative h-full {{ $barColor }}" | |
></div> | |
<!-- Tooltip --> | |
<div class="absolute inset-0 z-40 hidden" :id="chartId + dataIndex"> | |
<div class="flex h-full w-full items-center justify-center"> | |
@isset($tooltip) | |
{{ $tooltip }} | |
@else | |
<div class="bg-gray-800 shadow rounded-md p-1.5 text-white absolute mx-2 leading-none text-sm z-40 -mt-12"> | |
<span x-text="`${data.label}: ${data.value}`"></span> | |
</div> | |
@endisset | |
</div> | |
</div> | |
</div> | |
<div class="pl-3 w-20 leading-none"> | |
@isset($columnData) | |
{{ $columnData}} | |
@else | |
<div x-text="data.value" class="text-center text-gray-800 text-sm"></div> | |
@endisset | |
</div> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> | |
<div x-show="chartData.length === 0" class="flex w-full"> | |
<div class="flex flex-1 h-full flex-col space-y-4"> | |
<template x-for="i in 6"> | |
<div class="flex flex-1 space-x-4 justify-around"> | |
<div class="w-32"> | |
<div class="h-10 bg-gray-200 ml-auto animate-pulse rounded" :style="`width: ${Math.floor((Math.random() * 100) + 1)}%`"></div> | |
</div> | |
<div class="flex-1 flex space-x-4"> | |
<div class="h-10 relative w-full flex flex-1 h-full items-center bg-gray-100 rounded"> | |
<div :style="`width: ${Math.floor((Math.random() * 100) + 1)}%`" class="rounded animate-pulse transition ease-in duration-200 relative h-full bg-gray-200"></div> | |
</div> | |
<div class="h-10 w-16 items-center"> | |
<div class="animate-pulse transition ease-in duration-200 relative h-full bg-gray-200 rounded"></div> | |
</div> | |
</div> | |
</div> | |
</template> | |
</div> | |
</div> | |
</div> |
Wow, that's neat! Great color palette👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could you share a screenshot? Curious how it looks 👀