WifiSignal.tsx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. interface WifiSignalProps {
  2. signal: number | null | undefined; // dBm value
  3. className?: string;
  4. }
  5. /**
  6. * WiFi signal icon with 4 bars that fill based on signal strength.
  7. * - 4 bars: >= -50 dBm (excellent)
  8. * - 3 bars: >= -60 dBm (good)
  9. * - 2 bars: >= -70 dBm (fair)
  10. * - 1 bar: < -70 dBm (weak)
  11. * - 0 bars: no signal data
  12. */
  13. export function WifiSignal({ signal, className = "w-4 h-4" }: WifiSignalProps) {
  14. let bars = 0;
  15. if (signal != null) {
  16. if (signal >= -50) bars = 4;
  17. else if (signal >= -60) bars = 3;
  18. else if (signal >= -70) bars = 2;
  19. else bars = 1;
  20. }
  21. const activeColor = "#00ae42"; // bambu-green
  22. const inactiveColor = "#4a4a4a"; // dark gray
  23. return (
  24. <svg
  25. viewBox="0 0 24 24"
  26. fill="none"
  27. stroke="currentColor"
  28. strokeWidth="2"
  29. strokeLinecap="round"
  30. strokeLinejoin="round"
  31. className={className}
  32. >
  33. {/* Dot at bottom */}
  34. <circle
  35. cx="12"
  36. cy="20"
  37. r="1"
  38. fill={bars >= 1 ? activeColor : inactiveColor}
  39. stroke={bars >= 1 ? activeColor : inactiveColor}
  40. />
  41. {/* First arc (smallest) */}
  42. <path
  43. d="M8.5 16.5a5 5 0 0 1 7 0"
  44. stroke={bars >= 2 ? activeColor : inactiveColor}
  45. fill="none"
  46. />
  47. {/* Second arc */}
  48. <path
  49. d="M5 13a10 10 0 0 1 14 0"
  50. stroke={bars >= 3 ? activeColor : inactiveColor}
  51. fill="none"
  52. />
  53. {/* Third arc (largest) */}
  54. <path
  55. d="M1.5 9.5a15 15 0 0 1 21 0"
  56. stroke={bars >= 4 ? activeColor : inactiveColor}
  57. fill="none"
  58. />
  59. </svg>
  60. );
  61. }