Installation:
composer require jonpurvis/radial
Publish the package assets (if needed):
php artisan vendor:publish --provider="JonPurvis\Radial\RadialServiceProvider"
Register the Blade component:
Ensure RadialServiceProvider is registered in config/app.php under providers.
Add the namespace alias to config/app.php:
'aliases' => [
'Radial' => JonPurvis\Radial\Facades\Radial::class,
],
First Use Case: Create a simple donut chart in a Blade view:
<radial:donut
:data="[
['label' => 'Active', 'value' => 70, 'class' => 'text-blue-500'],
['label' => 'Inactive', 'value' => 30, 'class' => 'text-gray-500']
]"
label="User Status"
/>
Normalize Data: Ensure all segments sum to 100 (or a logical total) for accurate visual representation. Use array_sum() to validate:
$total = array_sum(array_column($data, 'value'));
$normalizedData = array_map(function($item) use ($total) {
return ['label' => $item['label'], 'value' => ($item['value'] / $total) * 100, 'class' => $item['class']];
}, $data);
Dynamic Data Binding: Fetch data from a model or API and bind it directly:
<radial:pie :data="$orders->groupBy('status')->map(fn($group) => [
'label' => $group->first()->status,
'value' => $group->count(),
'class' => "text-{$group->first()->status->colorClass()}"
])->toArray()"/>
Donut Charts:
label prop to dynamically update the center text:
<radial:donut :data="$data" :label="'Total: ' . $totalUsers"/>
Pie Charts:
<radial:pie :data="$data" label=""/>
Legends and Tooltips:
legend prop (default: true). Customize legend position or styling:
<radial:donut :data="$data" legend="bottom" legend-class="text-sm"/>
<radial:donut :data="$data">
<x-slot name="tooltip">
<div class="p-2">
<strong>{{ $label }}</strong>: {{ $value }}%
<br>
<small>Updated: {{ now()->format('m/d/Y') }}</small>
</div>
</x-slot>
</radial:donut>
Dark Mode Support:
Use Tailwind’s dark mode classes in your class prop (e.g., text-blue-500 dark:text-blue-300). Radial automatically respects the parent theme.
Responsive Design: Control size via inline styles or CSS:
<radial:donut :data="$data" style="width: 200px; height: 200px"/>
Or use Tailwind:
<div class="w-48 h-48">
<radial:pie :data="$data"/>
</div>
Livewire/Alpine Integration: Update charts dynamically with Alpine.js:
<div x-data="{ active: 'active' }">
<radial:donut :data="$data" x-bind:label="'Status: ' + active"/>
<button @click="active = 'inactive'">Toggle</button>
</div>
Zero Values:
value = 0. Validate data to avoid missing segments:
$data = array_filter($data, fn($item) => $item['value'] > 0);
Color Contrast:
text-gray-200) may blend into the background. Test in both light/dark mode:
// Ensure sufficient contrast
$validColors = ['text-red-500', 'text-green-500', 'text-blue-500', 'text-yellow-500'];
$data = array_map(function($item) use ($validColors) {
return ['label' => $item['label'], 'value' => $item['value'], 'class' => in_array($item['class'], $validColors) ? $item['class'] : 'text-gray-500'];
}, $data);
Blade Component Path:
radial namespace is registered in composer.json:
"autoload": {
"files": ["vendor/autoload.php"],
"psr-4": {
"App\\": "app/",
"Radial\\": "vendor/jonpurvis/radial/src/"
}
}
Missing Styles:
Check if radial.css is published and linked in your layout:
@vite(['resources/css/app.css', 'vendor/jonpurvis/radial/dist/radial.css'])
Or manually include:
<link href="{{ asset('vendor/radial/dist/radial.css') }}" rel="stylesheet">
Tooltip Overlaps: Adjust tooltip positioning via custom CSS:
.radial-tooltip {
margin-left: -10px !important;
margin-top: -5px !important;
}
Custom Animations: Extend the component by adding transition classes to the root element:
<radial:donut :data="$data" class="transition-all duration-500"/>
Then trigger animations via JavaScript:
document.querySelector('.radial-donut').classList.add('scale-110');
Server-Side Rendering: For SPAs, pre-render charts on the server to avoid hydration mismatches:
// In a Livewire component
public function render()
{
return view('livewire.chart')->with([
'chartData' => $this->prepareChartData(),
'isDarkMode' => request()->wantsJson() ? false : app()->isDarkMode(),
]);
}
Accessibility: Add ARIA labels and keyboard navigation:
<radial:pie
:data="$data"
aria-label="Revenue by quarter"
role="img"
/>
Customize focus styles:
.radial-segment:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
Theming: Override default colors globally by extending the CSS:
.radial-segment {
@apply stroke-current;
}
.radial-segment.text-custom {
@apply stroke-[#ff00ff];
}
Then use class="text-custom" in your data.
<div class="lazyload">
<radial:donut :data="$data"/>
</div>
document.querySelectorAll('.lazyload').forEach(el => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.innerHTML = entry.target.innerHTML;
observer.unobserve(entry.target);
}
});
});
observer.observe(el);
});
How can I help you explore Laravel packages today?