Componentmedia0.87 KB gzipZero dependencies
Mana Bar
Smooth energy meter with shimmer sweep.
Preview
Live Preview
MP64/100
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add mana-barOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { ManaBar } from "@/components/ui/mana-bar";
<ManaBar value={64} max={100} />Usage guidance
Use Mana Bar when a ticket stub surface needs Smooth energy meter with shimmer sweep. Keep props minimal and prefer composition with sibling stubs.
Avoid Mana Bar for long form flows or dense data grids where a dedicated layout block fits better.
Source code
mana-bar.tsxZero dependencies (only React + utils). Copy and paste directly into your project:
"use client";
import * as React from "react";
import { cn } from "./lib/utils";
export interface ManaBarProps extends React.HTMLAttributes<HTMLDivElement> {
value: number;
max?: number;
label?: string;
}
/** Mana bar: smooth arcane energy meter with shimmer sweep and motion-reduce fallback. */
export function ManaBar({ value, max = 100, label = "MP", className, ...props }: ManaBarProps) {
const pct = Math.max(0, Math.min(100, (value / Math.max(1, max)) * 100));
return (
<div className={cn("w-full min-w-44 select-none", className)} {...props}>
<style>{`@keyframes mpShimmer { from { transform: translateX(-100%); } to { transform: translateX(220%); } }`}</style>
<div className="mb-1 flex items-center justify-between font-mono text-[10px] uppercase tracking-[0.15em]">
<span className="text-muted-foreground">{label}</span>
<span className="font-bold tabular-nums text-foreground" role="status" aria-label={`${label} ${value} of ${max}`}>
{value}/{max}
</span>
</div>
<div
role="progressbar"
aria-valuemin={0}
aria-valuemax={max}
aria-valuenow={Math.max(0, Math.min(max, value))}
aria-label={label}
className="h-11 overflow-hidden rounded-md border-2 border-foreground bg-card p-1"
>
<div className="relative h-full w-full overflow-hidden rounded-[3px] bg-secondary">
<div
className="h-full rounded-[3px] bg-sky-500 transition-[width] duration-300 motion-reduce:transition-none"
style={{ width: `${pct}%` }}
/>
<span aria-hidden="true" className="absolute inset-y-0 w-1/3 bg-white/25 blur-[2px] animate-[mpShimmer_2.2s_ease-in-out_infinite] motion-reduce:animate-none" />
</div>
</div>
</div>
);
}
Props
| Prop | Type | Description |
|---|---|---|
| value | number | Current energy (required). |
| max | number | Maximum energy (default 100). |