spinner.tsx 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import { ComponentProps, For } from "solid-js"
  2. const outerIndices = new Set([1, 2, 4, 7, 8, 11, 13, 14])
  3. const cornerIndices = new Set([0, 3, 12, 15])
  4. const squares = Array.from({ length: 16 }, (_, i) => ({
  5. id: i,
  6. x: (i % 4) * 4,
  7. y: Math.floor(i / 4) * 4,
  8. delay: Math.random() * 1.5,
  9. duration: 1 + Math.random() * 1,
  10. outer: outerIndices.has(i),
  11. corner: cornerIndices.has(i),
  12. }))
  13. export function Spinner(props: {
  14. class?: string
  15. classList?: ComponentProps<"div">["classList"]
  16. style?: ComponentProps<"div">["style"]
  17. }) {
  18. return (
  19. <svg
  20. {...props}
  21. viewBox="0 0 15 15"
  22. data-component="spinner"
  23. classList={{
  24. ...props.classList,
  25. [props.class ?? ""]: !!props.class,
  26. }}
  27. fill="currentColor"
  28. >
  29. <For each={squares}>
  30. {(square) => (
  31. <rect
  32. x={square.x}
  33. y={square.y}
  34. width="3"
  35. height="3"
  36. rx="1"
  37. style={{
  38. opacity: square.corner ? 0 : undefined,
  39. animation: square.corner
  40. ? undefined
  41. : `${square.outer ? "pulse-opacity-dim" : "pulse-opacity"} ${square.duration}s ease-in-out infinite`,
  42. "animation-fill-mode": square.corner ? undefined : "both",
  43. "animation-delay": square.corner ? undefined : `${square.delay}s`,
  44. }}
  45. />
  46. )}
  47. </For>
  48. </svg>
  49. )
  50. }