elements
lifecycle
browser
- useAudio
- useBattery
- useBluetooth
- useBreakpoints
- useBroadcastChannel
- useBrowserLocation
- useClipboard
- useCopy
- useCssVar
- useDisplayMedia
- useDocumentEvent
- useDocumentTitle
- useDocumentVisibility
- useEventListener
- useEventSource
- useEyeDropper
- useFavicon
- useFileSystemAccess
- useFps
- useFullscreen
- useGamepad
- useGeolocation
- useMeasure
- useMediaControls
- useMediaQuery
- useMemory
- useNetwork
- useObjectUrl
- useOnline
- useOtpCredential
- usePermission
- usePictureInPicture
- usePointerLock
- usePostMessage
- useRaf
- useShare
- useSpeechRecognition
- useSpeechSynthesis
- useSticky
- useVibrate
- useVirtualKeyboard
- useWakeLock
- useWebSocket
utilities
state
- useBoolean
- useControllableState
- useCookie
- useCookies
- useCounter
- useCycleList
- useDefault
- useDisclosure
- useField
- useHash
- useList
- useLocalStorage
- useMap
- useMask
- useMergedRef
- useObject
- useOffsetPagination
- useQueue
- useRafState
- useRefState
- useSessionStorage
- useSet
- useStateHistory
- useStep
- useStorage
- useToggle
- useUrlSearchParam
- useUrlSearchParams
- useValidatedState
- useWizard
user
sensors
- useDeviceMotion
- useDeviceOrientation
- useHotkeys
- useIdle
- useInfiniteScroll
- useIntersectionObserver
- useKeyboard
- useKeyPress
- useKeysPressed
- useMouse
- useMutationObserver
- useOrientation
- usePageLeave
- useParallax
- usePerformanceObserver
- useResizeObserver
- useScroll
- useScrollIntoView
- useScrollTo
- useSwipe
- useTextSelection
- useVisibility
- useWindowEvent
- useWindowFocus
- useWindowScroll
- useWindowSize
API not supported, make sure to check for compatibility with different browsers when using this API
import { useBattery } from '@siberiacancode/reactuse';
import {
BatteryChargingIcon,
BatteryFullIcon,
BatteryLowIcon,
BatteryMediumIcon,
BatteryWarningIcon,
Loader2Icon
} from 'lucide-react';
import { cn } from '@/utils/lib';
const getBatteryIcon = (level: number) => {
if (level > 80) return BatteryFullIcon;
if (level > 40) return BatteryMediumIcon;
if (level > 15) return BatteryLowIcon;
return BatteryWarningIcon;
};
const formatTime = (seconds: number) => {
if (!Number.isFinite(seconds) || seconds <= 0) return '--';
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
if (h > 0) return `${h}h ${m}m`;
return `${m}m`;
};
const Demo = () => {
const battery = useBattery();
if (!battery.supported)
return (
<p>
API not supported, make sure to check for compatibility with different browsers when using
this{' '}
<a
href='https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getBattery'
rel='noreferrer'
target='_blank'
>
API
</a>
</p>
);
if (battery.value.loading) {
return (
<section className='flex justify-center'>
<div className='relative flex h-[520px] w-76 items-center justify-center rounded-4xl border pt-12'>
<div className='bg-border absolute top-3 left-1/2 h-5 w-18 -translate-x-1/2 rounded-full' />
<Loader2Icon className='size-5 animate-spin' />
</div>
</section>
);
}
const level = Math.round((battery.value.level ?? 0) * 100);
const Icon = battery.value.charging ? BatteryChargingIcon : getBatteryIcon(level);
const lowBattery = level <= 15 && !battery.value.charging;
return (
<section className='flex justify-center'>
<div className='relative flex h-[430px] w-70 flex-col gap-7 rounded-4xl border px-6 pt-10 pb-8'>
<div className='bg-border absolute top-3 left-1/2 h-5 w-18 -translate-x-1/2 rounded-full' />
<div className='flex h-full flex-col gap-6 pt-6'>
<div className='flex flex-col items-center gap-2'>
<Icon className={cn('ml-2 size-30', lowBattery ? 'text-red-500' : 'text-foreground')} />
<div className='flex flex-col items-center gap-1'>
<div className='text-5xl font-semibold tracking-tight'>{level}%</div>
<span className='text-muted-foreground text-xs tracking-wider uppercase'>
{battery.value.charging ? 'Charging' : 'Battery'}
</span>
</div>
</div>
<div className='mt-auto flex flex-col gap-2 border-t pt-4'>
<div className='flex items-center justify-between text-xs'>
<span className='text-muted-foreground'>Status</span>
<span className='font-medium'>
{battery.value.charging ? 'Charging' : 'Discharging'}
</span>
</div>
<div className='flex items-center justify-between text-xs'>
<span className='text-muted-foreground'>Charge time</span>
<span className='font-medium'>
{formatTime(battery.value.chargingTime ?? Infinity)}
</span>
</div>
<div className='flex items-center justify-between text-xs'>
<span className='text-muted-foreground'>Time left</span>
<span className='font-medium'>
{formatTime(battery.value.dischargingTime ?? Infinity)}
</span>
</div>
</div>
</div>
</div>
</section>
);
};
export default Demo;
This hook uses navigator.getBattery browser api to provide enhanced functionality. Make sure to check for compatibility with different browsers when using this api
Installation
pnpm add @siberiacancode/reactuseUsage
const { supported, loading, charging, chargingTime, dischargingTime, level } = useBattery();Type Declarations
export interface BatteryManager extends EventTarget {
charging: boolean;
chargingTime: number;
dischargingTime: number;
level: number;
}
interface Navigator {
readonly getBattery: () => Promise<BatteryManager>;
}
export interface UseBatteryValue {
/** Is charging battery? */
charging: boolean;
/** Time until the battery is fully charged */
chargingTime: number;
/** Time until the battery is completely discharged */
dischargingTime: number;
/** Battery charge level from 0 to 1 */
level: number;
/** Is battery information loading? */
loading: boolean;
}
export interface UseBatteryReturn {
/** Whether the battery api is supported*/
supported: boolean;
/** The use battery value type */
value: UseBatteryValue;
}API
Returns
UseBatteryStateReturnContributors
ddebabinbbabinhhywaxNNikitaGGorilla Dev
Last updated on