Spinner

Loading indicator. Spinning SVG circle (default) or three-dot pulse alternative.

Overview

The Spinner component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.

Why this exists

Spinners indicate that content or an action is loading. They prevent users from thinking the interface is frozen.

Mental model

A spinner is a loading indicator. Use it for actions under 10 seconds. For longer waits, use a progress bar with estimated time.

When to use

• Button loading state during form submit • Page or section loading • Data fetching in tables • Lazy image loading

When not to use

• Do not use for waits over 10 seconds — use progress bar • Avoid as a loading placeholder for images — use skeleton • Do not use when the action is instant

Basic example

The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.

Variants

Each variant communicates a different meaning. Choose based on priority, not aesthetics.

Single default variant.

Sizes

Size should match the importance and context of the component.

  • xs — xs size.
  • sm — sm size.
  • md — md size.
  • lg — lg size.
  • xl — xl size.

States

This component reacts seamlessly to the following interaction and data states:

  • default — Resting appearance before interaction.
  • hover — Pointer is over the element — visual feedback via color or shadow.
  • focus — Keyboard or tab focus — shows ring indicator for accessibility.
  • active — Currently selected or in use.
  • disabled — Non-interactive — grayed out, cursor not-allowed.

Anatomy

• Spinning circle — SVG or CSS animation • Container — centered within parent • Label — optional"Loading…" text

Usage guidelines

  • Keep spinners small for buttons, medium for sections.
  • Always pair with text for screen readers.
  • Use skeleton for content loading, not spinners.

Do and Don't

Do

  • Pair with text for a11y.
  • Use for short waits.
  • Size to context.

Don't

  • Do not use for long waits.
  • Do not use alone for content loading.
  • Do not spin unnecessarily.

Accessibility

Wrap with role="status" and aria-live. Hide decorative spinners from screen readers with aria-hidden.

Role:status

Customization

Color follows current text color or primary token.

Compose with React cva()

Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.

import { cva, cn, type VariantProps } from '@byteion/react';

const mySpinner = cva('base classes…', {
 variants: {
  accent: { soft:'border-primary-200', loud:'border-primary-500' },
 },
 defaultVariants: { accent:'soft' },
});

type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof mySpinner>;

Compose with Vue cva()

Use the exportedcva() +cn() utilities inside standard Vue setup blocks.

<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';

interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();

const mySpinner = cva('base classes…', {
  variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});

const cls = computed(() => mySpinner({ accent: props.accent, class: attrs.class as string | undefined }));
</script>

Runtime events

Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.

HTML / JS events

No HTML runtime events are declared by this adapter.

React callbacks

No React callback events are declared by this adapter.

Vue emits

No Vue emitted events are declared by this adapter.

Remote / AJAX

This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.

API Reference

Static HTML. No JS required.

HTML Data Attributes

No custom data attributes required.

React Props · SpinnerProps

Extracted directly fromreact/src/components/Spinner.tsx.

export interface SpinnerProps
  extends Omit<HTMLAttributes<HTMLElement>, 'children'>,
    VariantProps<typeof spinner> {
  /** Visible label shown beside the spinner. Adds `role="status"` wrapper. */
  label?: ReactNode;
  /** Accessible label when no visible label is rendered. Defaults to "Loading". */
  'aria-label'?: string;
  /** Render the dot-pulse animation instead of the circular spinner. */
  variant?: 'spin' | 'dot-pulse';
}

React Variant Schema

Internal variant composition defined viacva().

cva('animate-spin', {
  variants: {
    size: {
      xs: 'h-4  w-4',
      sm: 'h-5  w-5',
      md: 'h-6  w-6',
      lg: 'h-8  w-8',
      xl: 'h-12 w-12',
    },
    tone: {
      primary: 'text-primary-600',
      success: 'text-success-600',
      warning: 'text-warning-500',
      danger:  'text-danger-600',
      neutral: 'text-muted-foreground',
      current: 'text-current',
    },
  },
  defaultVariants: { size: 'md', tone: 'primary' },
})

Vue Props · SpinnerProps

Extracted directly fromvue/src/components/Spinner.vue.

export interface SpinnerProps {
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
  tone?: 'primary' | 'success' | 'warning' | 'danger' | 'neutral' | 'current';
  /** Render the dot-pulse animation instead of the circular spinner. */
  variant?: 'spin' | 'dot-pulse';
  /** Visible label shown beside the spinner. Adds `role="status"` wrapper. */
  label?: string;
  /** Accessible label when no visible label is rendered. Defaults to "Loading". */
  ariaLabel?: string;
}

Developer tips

• Best practice: for page loads, show spinner within 200ms — before that, the load is fast enough to skip.

Common mistakes

Avoid hardcoded neutral colors, placeholder-only labels, duplicated primary actions, and missing keyboard states. Keep this component on Byteion tokens so dashboard, admin, POS, ERP, ecommerce back-office, Laravel, React, and Vue starter-kit screens can be rebranded without rewriting markup.

Production usage tips

Use the canonical HTML as the source of truth, keep React and Vue wrappers aligned with the documented variants, test dark mode and branded themes before release, and wire interactive behavior through data-bi-* attributes instead of styling hooks.

Premium examples

Advanced patterns available in Byteion Pro:

• Skeleton + spinner hybrid for content areas • Branded spinner animation (logo morph)

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.

Explore Pro Components