Перейти к содержимому

Индикатор загрузки

Анимированный индикатор загрузки для ожидающих отправки данных, запросов и состояний занятости в интерфейсе — готовый к использованию значок для любого элемента управления в стиле «необрутализм».

import {
  Item,
  ItemContent,

Spinner — одна анимированная иконка, сигнализирующая о in-flight операции. Оборачивает LoaderIcon из lucide-react с animate-spin и из коробки несёт role="status" плюс aria-label — без primitive-библиотеки, поэтому оба backend'а делят одну реализацию, а currentColor наследуется, чтобы совпасть с любым необруталистским контролом рядом.

Когда это пригодится:

  • Pending-отправки — подставьте его в кнопку, пока идёт mutation; label остаётся на месте.
  • Inline-состояния fetch — badges, input groups и ячейки таблиц, ждущие данные.
  • Секционные загрузки — сочетайте с Empty, пока панель стримится.

Установка

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/spinner.json
npx shadcn@latest add https://neobrutalism.com/r/base/spinner.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/spinner.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/spinner.json

Скопируйте и вставьте следующий код в свой проект.

components/ui/spinner.tsx
import { Loader2Icon } from "lucide-react"

import { cn } from "@/lib/utils"

function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
  return (
    <Loader2Icon
      data-slot="spinner"
      role="status"
      aria-label="Loading"
      className={cn("size-4 animate-spin", className)}
      {...props}
    />
  )
}

export { Spinner }

Обновите пути импортов в соответствии со структурой вашего проекта.

Использование

import { Spinner } from "@/components/ui/spinner"
<Spinner />

Настройка

Вы можете заменить стандартную иконку спиннера любой другой, отредактировав компонент Spinner.

import { LoaderIcon } from "lucide-react"

import { cn } from "@/lib/utils"
components/ui/spinner.tsx
import { LoaderIcon } from "lucide-react"
 
import { cn } from "@/lib/utils"
 
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
  return (
    <LoaderIcon
      role="status"
      aria-label="Loading"
      className={cn("size-4 animate-spin", className)}
      {...props}
    />
  )
}
 
export { Spinner }

Примеры

Размер

Используйте служебный класс size-*, чтобы изменить размер спиннера.

import { Spinner } from "@/components/ui/spinner"

export function SpinnerSize() {

Button

Добавьте спиннер к кнопке, чтобы показать состояние загрузки. Поместите <Spinner /> перед подписью с data-icon="inline-start" для позиции в начале или после подписи с data-icon="inline-end" для позиции в конце.

import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"

Badge

Добавьте спиннер к бейджу, чтобы показать состояние загрузки. Поместите <Spinner /> перед подписью с data-icon="inline-start" для позиции в начале или после подписи с data-icon="inline-end" для позиции в конце.

import { Badge } from "@/components/ui/badge"
import { Spinner } from "@/components/ui/spinner"

Input Group

import { ArrowUpIcon } from "lucide-react"

import {

Empty

import { Button } from "@/components/ui/button"
import {
  Empty,

RTL

Чтобы включить поддержку RTL в Neobrutalism, см. руководство по настройке RTL.

"use client"

import * as React from "react"

Доступность

Spinner рендерит role="status" с aria-label="Loading", поэтому программы чтения с экрана объявляют состояние загрузки без дополнительной обвязки. Когда соседний текст уже описывает состояние («Сохранение…»), передайте спиннеру aria-hidden="true" — одного объявления достаточно. Для целой области, переходящей в loading, ставьте aria-busy="true" на контейнер.