dotUI
dotUI
beta
  1. Hooks
  2. Sensors hooks
  3. useBattery

useBattery

Track the battery status of a user’s device with useBattery.

"use client";

import {
  BatteryChargingIcon,
  BatteryFullIcon,
  BatteryLowIcon,
  BatteryMediumIcon,
  BatteryWarning,
  Loader2Icon,
} from "lucide-react";
import { useBattery } from "@/lib/hooks/use-battery";

function Demo() {
  const { isLoading, isSupported, isCharging, level } = useBattery();

  const size = 120;

  return (
    <div className="text-center">
      <h2 className="text-xl font-semibold">Battery status</h2>
      <div className="mt-4 flex items-center justify-center space-x-4">
        {isLoading ? (
          <Loader2Icon className="animate-spin" />
        ) : !isSupported ? (
          <p className="text-fg-muted">Battery status API is not supported in your browser.</p>
        ) : (
          <>
            <span className="text-5xl font-bold">{Math.round(level * 100)}%</span>
            {isCharging ? (
              <BatteryChargingIcon size={size} />
            ) : level === 1 ? (
              <BatteryFullIcon size={size} />
            ) : level > 0.5 ? (
              <BatteryMediumIcon size={size} />
            ) : level > 0.2 ? (
              <BatteryLowIcon size={size} />
            ) : (
              <BatteryWarning size={size} />
            )}
          </>
        )}
      </div>
    </div>
  );
}

Installation

Copy and paste the following code into your project.

import React from "react";

interface BatteryManager extends EventTarget {
  charging: boolean;
  chargingTime: number;
  dischargingTime: number;
  level: number;
}

type NavigatorWithBattery = Navigator & {
  getBattery: () => Promise<BatteryManager>;
};

export function useBattery() {
  const [state, setState] = React.useState<{
    isSupported: boolean;
    isLoading: boolean;
    isCharging: boolean;
    level: number;
    chargingTime: number;
    dischargingTime: number;
  }>({
    isSupported: false,
    isLoading: true,
    isCharging: false,
    level: 1,
    chargingTime: 0,
    dischargingTime: 0,
  });

  React.useEffect(() => {
    if (!(navigator as NavigatorWithBattery).getBattery) {
      setState((s) => ({
        ...s,
        isSupported: false,
        isLoading: false,
      }));
      return;
    }

    let battery: BatteryManager | null;

    const handleChange = () => {
      if (!battery) return;
      setState({
        isSupported: true,
        isLoading: false,
        level: battery.level,
        isCharging: battery.charging,
        chargingTime: battery.chargingTime,
        dischargingTime: battery.dischargingTime,
      });
    };

    void (navigator as NavigatorWithBattery).getBattery().then((b) => {
      battery = b;
      handleChange();

      b.addEventListener("levelchange", handleChange);
      b.addEventListener("chargingchange", handleChange);
      b.addEventListener("chargingtimechange", handleChange);
      b.addEventListener("dischargingtimechange", handleChange);
    });

    return () => {
      if (battery) {
        battery.removeEventListener("levelchange", handleChange);
        battery.removeEventListener("chargingchange", handleChange);
        battery.removeEventListener("chargingtimechange", handleChange);
        battery.removeEventListener("dischargingtimechange", handleChange);
      }
    };
  }, []);

  return state;
}

Update the import paths to match your project setup.

Return values

NameTypeDescription
isSupported
boolean
Indicates whether the Battery Status API is supported in the user’s browser.
isLoading
boolean
Indicates if the battery information is still loading.
isCharging
boolean
Represents whether the system’s battery is charging. true means the battery is charging, false means it’s not.
level
number
Represents the level of the system’s battery. 0.0 means that the system’s battery is completely discharged, and 1.0 means the battery is completely charged.
chargingTime
number
Represents the time remaining in seconds until the system’s battery is fully charged.
dischargingTime
number
Represents the time remaining in seconds until the system’s battery is completely discharged and the system is about to be suspended.

Built by mehdibha. The source code is available on GitHub.