# Alert, Badge, Empty, Skeleton, Spinner, and Stat

> Alert, Badge, Empty, Skeleton, Spinner, and Stat: anatomy, keyboard behavior, state, and theming in Askr.

Source: [https://askrjs.com/docs/components/alert-badge-empty-skeleton-spinner-and-stat](https://askrjs.com/docs/components/alert-badge-empty-skeleton-spinner-and-stat)

Status: stable. Packages: @askrjs/themes/alert, @askrjs/themes/badge, @askrjs/themes/empty, @askrjs/themes/skeleton, @askrjs/themes/spinner, @askrjs/themes/components.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

```tsx
import { Alert, AlertDescription, AlertTitle, Badge, Empty, EmptyDescription, EmptyTitle, Spinner } from '@askrjs/themes/components';

{query.pending ? <Spinner aria-label="Loading projects" /> :
 query.error ? <Alert variant="danger"><AlertTitle>Could not load projects</AlertTitle><AlertDescription>{query.error.message}</AlertDescription></Alert> :
 query.data.length === 0 ? <Empty><EmptyTitle>No projects</EmptyTitle><EmptyDescription>Create a project to get started.</EmptyDescription></Empty> :
 <Badge>{query.data.length} active</Badge>}
```

## Published props

Generated from the TypeScript declarations shipped by the installed package.

### `AlertProps`

Import from `@askrjs/themes/components`.

- `actions?: unknown;`
- `children?: unknown;`
- `description?: unknown;`
- `dismissLabel?: string | undefined;`
- `icon?: unknown;`
- `onDismiss?: (() => void) | undefined;`
- `ref?: Ref<HTMLDivElement>;`
- `title?: unknown;`
- `titleAs?: AlertHeadingTag | undefined;`
- `variant?: AlertVariant | undefined;`

### `AspectRatioAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `ratio?: string | number | undefined;`
- `ref?: Ref<unknown>;`
- `style?: unknown;`

### `AspectRatioProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `ratio?: string | number | undefined;`
- `ref?: Ref<HTMLDivElement>;`
- `style?: unknown;`

### `BadgeAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `ref?: Ref<unknown>;`
- `variant?: BadgeVariant | undefined;`

### `BadgeOwnProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `variant?: BadgeVariant | undefined;`

### `BadgeProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `ref?: Ref<HTMLSpanElement>;`
- `variant?: BadgeVariant | undefined;`

### `BlockAsChildProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `asChild: true;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children: JSXElement;`
- `className?: string | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `BlockDivProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: "div" | undefined;`
- `asChild?: false | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `BlockElementProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: TElement | undefined;`
- `asChild?: false | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `BlockNativeProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: "a" | "article" | "aside" | "div" | "form" | "footer" | "header" | "li" | "main" | "nav" | "ol" | "section" | "span" | "ul" | undefined;`
- `asChild?: false | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | ((() => IntrinsicClassValue) & string) | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `BlockOwnProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: BlockElement | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `BlockProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `asChild?: boolean | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | ((() => IntrinsicClassValue) & string) | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `BlockSpanProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: "span" | undefined;`
- `asChild?: false | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `ButtonAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: ButtonAsChildElement;`
- `disabled?: boolean | undefined;`
- `onPress?: ((e: PressEvent) => void) | undefined;`
- `ref?: Ref<Element>;`
- `size?: ButtonSize | undefined;`
- `type?: undefined;`
- `variant?: ButtonVariant | undefined;`
- `width?: ButtonWidth | undefined;`

### `ButtonGroupProps`

Import from `@askrjs/themes/components`.

- `attached?: boolean | undefined;`
- `children?: unknown;`
- `orientation?: ButtonGroupOrientation | undefined;`
- `ref?: Ref<HTMLDivElement>;`

### `ButtonNativeProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `disabled?: boolean | undefined;`
- `onPress?: ((e: PressEvent) => void) | undefined;`
- `ref?: Ref<HTMLButtonElement>;`
- `size?: ButtonSize | undefined;`
- `type?: "button" | "submit" | "reset" | undefined;`
- `variant?: ButtonVariant | undefined;`
- `width?: ButtonWidth | undefined;`

### `ButtonProps`

Import from `@askrjs/themes/components`.

- `asChild?: boolean | undefined;`
- `children?: unknown;`
- `disabled?: boolean | undefined;`
- `onPress?: ((e: PressEvent) => void) | undefined;`
- `ref?: ((value: Element | null) => void) | { current: Element | null; } | ((value: HTMLButtonElement | null) => void) | { current: HTMLButtonElement | null; } | null | undefined;`
- `size?: ButtonSize | undefined;`
- `type?: "button" | "submit" | "reset" | undefined;`
- `variant?: ButtonVariant | undefined;`
- `width?: ButtonWidth | undefined;`

### `CardActionProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`

### `CardContentProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`

### `CardDescriptionProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLParagraphElement>;`

### `CardFooterProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`

### `CardHeaderProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`

### `CardProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`
- `variant?: CardVariant | undefined;`

### `CardTitleProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLHeadingElement>;`
- `titleAs?: CardTitleHeadingTag | undefined;` — Choose the level that follows the surrounding document hierarchy.

### `CatalogComponentProps`

Import from `@askrjs/themes/components`.

- `as?: keyof JSX.IntrinsicElements | undefined;`
- `asChild?: boolean | undefined;`
- `children?: unknown;`
- `class?: string | undefined;`
- `ref?: Ref<HTMLElement>;`

### `CloseNativeProps`

Import from `@askrjs/themes/components`.

- `label?: string | undefined;`

### `CloseOwnProps`

Import from `@askrjs/themes/components`.

- `label?: string | undefined;`

### `CommandPaletteContentProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `closeOnBackdrop?: boolean | undefined;`
- `closeOnEscape?: boolean | undefined;`
- `description?: string | undefined;`
- `initialFocus?: string | false | (() => HTMLElement | null) | undefined;`
- `onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;`
- `onInteractOutside?: ((event: Event) => void) | undefined;`
- `onPointerDownOutside?: ((event: PointerEvent) => void) | undefined;`
- `overlayProps?: DialogOverlayProps | undefined;`
- `title: string;`

### `CommandPaletteLinkProps`

Import from `@askrjs/themes/components`.

- `closeOnSelect?: boolean | undefined;`
- `onBeforeNavigate?: ((event: Event) => void) | undefined;`

### `CommandPaletteListProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLUListElement>;`

### `ContainerProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: "div" | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `size?: BlockSize | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `CopyButtonProps`

Import from `@askrjs/themes/components`.

- `failureMessage?: string | undefined;`
- `label: string;`
- `resetAfter?: number | undefined;`
- `successMessage?: string | undefined;`
- `text: string;`

### `DialogProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `defaultOpen?: boolean | undefined;`
- `id?: string | undefined;`
- `modal?: boolean | undefined;`
- `onOpenChange?: ((open: boolean) => void) | undefined;`
- `open?: boolean | undefined;`

### `EmptyStateProps`

Import from `@askrjs/themes/components`.

- `action?: unknown;`
- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: "div" | undefined;`
- `asChild?: false | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | undefined;`
- `description?: unknown;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `icon?: unknown;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `title?: unknown;`
- `titleAs?: EmptyStateHeadingTag | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `FieldErrorProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLParagraphElement>;`

### `FieldHintProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLParagraphElement>;`

### `FieldProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `invalid?: boolean | undefined;`
- `ref?: Ref<HTMLDivElement>;`

### `FooterContentProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`

### `FooterDescriptionProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLParagraphElement>;`

### `FooterLinkProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLAnchorElement>;`

### `FooterLinksProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLElement>;`

### `FooterSectionProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLDivElement>;`

### `FooterTitleProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `ref?: Ref<HTMLHeadingElement>;`

### `GridProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<GridAlign> | undefined;`
- `as?: TElement | undefined;`
- `children?: unknown;`
- `columns?: ResponsiveValue<GridColumns> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `ref?: Ref<HTMLElement>;`

### `HeaderProps`

Import from `@askrjs/themes/components`.

- `position?: "sticky" | "static" | undefined;`
- `sticky?: boolean | undefined;`

### `InputGroupProps`

Import from `@askrjs/themes/components`.

- `attached?: boolean | undefined;`
- `children?: unknown;`
- `orientation?: InputGroupOrientation | undefined;`
- `ref?: Ref<HTMLDivElement>;`

### `InputGroupTextAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `ref?: Ref<unknown>;`

### `InputGroupTextProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `ref?: Ref<HTMLSpanElement>;`

### `LegacyLayoutProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `as?: BlockElement | undefined;`
- `asChild?: boolean | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `className?: string | undefined;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<LegacySpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `p?: ResponsiveValue<LegacySpace> | undefined;`
- `padding?: ResponsiveValue<LegacySpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<LegacyWrap> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `MetaStripProps`

Import from `@askrjs/themes/components`.

- `density?: MetaStripDensity | undefined;`
- `items: readonly MetaStripItem[];`
- `ref?: Ref<HTMLDListElement>;`

### `NavbarProps`

Import from `@askrjs/themes/components`.

- `breakpoint?: false | NavbarCollapseBreakpoint | undefined;`
- `collapseAt?: false | NavbarCollapseBreakpoint | undefined;`
- `collapseIcon?: unknown;`
- `collapseLabel?: string | undefined;`

### `NavBrandProps`

Import from `@askrjs/themes/components`.

- `align?: ResponsiveValue<BlockAlign> | undefined;`
- `asChild?: boolean | undefined;`
- `background?: ResponsiveValue<BlockBackground> | undefined;`
- `border?: ResponsiveValue<boolean> | undefined;`
- `borderBottom?: ResponsiveValue<boolean> | undefined;`
- `borderRight?: ResponsiveValue<boolean> | undefined;`
- `borderTop?: ResponsiveValue<boolean> | undefined;`
- `center?: ResponsiveValue<boolean> | undefined;`
- `children?: unknown;`
- `direction?: ResponsiveValue<BlockDirection> | undefined;`
- `gap?: ResponsiveValue<BlockSpace> | undefined;`
- `grow?: ResponsiveValue<number | boolean> | undefined;`
- `height?: ResponsiveValue<BlockSize> | undefined;`
- `hide?: ResponsiveValue<boolean> | undefined;`
- `justify?: ResponsiveValue<BlockJustify> | undefined;`
- `margin?: ResponsiveValue<BlockMargin> | undefined;`
- `marginX?: ResponsiveValue<BlockMargin> | undefined;`
- `marginY?: ResponsiveValue<BlockMargin> | undefined;`
- `maxHeight?: ResponsiveValue<BlockSize> | undefined;`
- `maxWidth?: ResponsiveValue<BlockSize> | undefined;`
- `minHeight?: ResponsiveValue<BlockSize> | undefined;`
- `minWidth?: ResponsiveValue<BlockSize> | undefined;`
- `padding?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingX?: ResponsiveValue<BlockSpace> | undefined;`
- `paddingY?: ResponsiveValue<BlockSpace> | undefined;`
- `radius?: ResponsiveValue<BlockRadius> | undefined;`
- `ref?: Ref<unknown>;`
- `rowFrom?: BlockRowFrom | undefined;`
- `shadow?: ResponsiveValue<BlockShadow> | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `sticky?: boolean | undefined;`
- `top?: ResponsiveValue<BlockSpace> | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`
- `wrap?: ResponsiveValue<boolean> | undefined;`
- `zIndex?: ResponsiveValue<BlockZIndex> | undefined;`

### `NavDropdownProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `label: unknown;`

### `NavGroupProps`

Import from `@askrjs/themes/components`.

- `label?: unknown;`
- `title?: unknown;`

### `NavItemAsChildProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `asChild: true;`
- `children: JSXElement;`
- `ref?: Ref<unknown>;`

### `NavItemProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `asChild?: false | undefined;`
- `children?: unknown;`
- `ref?: Ref<HTMLAnchorElement>;`

### `NavLinkProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `match?: NavLinkMatch | undefined;`

### `PageHeaderProps`

Import from `@askrjs/themes/components`.

- `actions?: unknown;`
- `description?: unknown;`
- `direction?: undefined;`
- `rowFrom?: undefined;`
- `title: unknown;`

### `PillProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `match?: NavLinkMatch | undefined;`

### `PillsAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `ref?: Ref<unknown>;`

### `PillsProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `ref?: Ref<HTMLElement>;`

### `SeparatorAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `decorative?: boolean | undefined;`
- `orientation?: "vertical" | "horizontal" | undefined;`
- `ref?: Ref<unknown>;`

### `SeparatorNativeProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `decorative?: boolean | undefined;`
- `orientation?: "vertical" | "horizontal" | undefined;`
- `ref?: Ref<HTMLDivElement>;`

### `SeparatorOwnProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `decorative?: boolean | undefined;`
- `orientation?: "vertical" | "horizontal" | undefined;`

### `SeparatorProps`

Import from `@askrjs/themes/components`.

- `asChild?: boolean | undefined;`
- `children?: unknown;`
- `decorative?: boolean | undefined;`
- `orientation?: "vertical" | "horizontal" | undefined;`
- `ref?: ((value: unknown) => void) | { current: unknown; } | ((value: HTMLDivElement | null) => void) | { current: HTMLDivElement | null; } | null | undefined;`

### `SidebarButtonProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `asChild?: boolean | undefined;`
- `size?: "sm" | "lg" | "default" | undefined;`
- `tooltip?: string | undefined;`
- `tooltipSide?: SidebarTooltipSide | undefined;`
- `variant?: "default" | "outline" | undefined;`

### `SidebarPartProps`

Import from `@askrjs/themes/components`.

- `as?: keyof JSX.IntrinsicElements | undefined;`
- `asChild?: boolean | undefined;`

### `SidebarProps`

Import from `@askrjs/themes/components`.

- `collapsible?: SidebarCollapsible | undefined;`
- `shrink?: ResponsiveValue<number | boolean> | undefined;`
- `side?: SidebarSide | undefined;`
- `variant?: SidebarVariant | undefined;`
- `width?: ResponsiveValue<BlockSize> | undefined;`

### `SidebarRailProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `asChild?: boolean | undefined;`
- `size?: "sm" | "lg" | "default" | undefined;`
- `tooltip?: string | undefined;`
- `tooltipSide?: SidebarTooltipSide | undefined;`
- `variant?: "default" | "outline" | undefined;`

### `SkeletonAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `height?: string | number | undefined;`
- `ref?: Ref<unknown>;`
- `width?: string | number | undefined;`

### `SkeletonOwnProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `height?: string | number | undefined;`
- `width?: string | number | undefined;`

### `SkeletonProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `height?: string | number | undefined;`
- `ref?: Ref<HTMLDivElement>;`
- `width?: string | number | undefined;`

### `SpinnerOwnProps`

Import from `@askrjs/themes/components`.

- `label?: string | undefined;`
- `size?: SpinnerSize | undefined;`

### `SpinnerProps`

Import from `@askrjs/themes/components`.

- `label?: string | undefined;`
- `size?: SpinnerSize | undefined;`

### `TabProps`

Import from `@askrjs/themes/components`.

- `active?: boolean | undefined;`
- `match?: NavLinkMatch | undefined;`

### `TabsAsChildProps`

Import from `@askrjs/themes/components`.

- `asChild: true;`
- `children: JSXElement;`
- `ref?: Ref<unknown>;`

### `TabsProps`

Import from `@askrjs/themes/components`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `ref?: Ref<HTMLElement>;`

### `TextProps`

Import from `@askrjs/themes/components`.

- `as?: TextElement | undefined;`
- `children?: unknown;`
- `font?: TextFont | undefined;`
- `numeric?: TextNumeric | undefined;`
- `ref?: Ref<HTMLElement>;`
- `size?: TextSize | undefined;`
- `tone?: TextTone | undefined;`
- `truncate?: boolean | undefined;`
- `weight?: TextWeight | undefined;`
- `wrap?: TextWrap | undefined;`

### `ThemePickerProps`

Import from `@askrjs/themes/components`.

- `label?: string | undefined;`
- `themes?: readonly ThemeOption[] | undefined;`

### `ThemeScopeProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `defaultTheme?: ThemeName | undefined;`
- `storageKey?: string | undefined;`
- `themes?: readonly ThemeOption[] | undefined;`

### `ThemeToggleProps`

Import from `@askrjs/themes/components`.

- `children?: unknown;`
- `darkIcon?: unknown;`
- `lightIcon?: unknown;`
- `onPress?: ((event: PressEvent) => void) | undefined;`
- `systemIcon?: unknown;`
- `themes?: readonly ThemeName[] | undefined;`

### `ToolbarProps`

Import from `@askrjs/themes/components`.

- `actions?: unknown;`
- `direction?: undefined;`
- `rowFrom?: undefined;`
- `title: unknown;`

### `VirtualListAsChildProps`

Import from `@askrjs/themes/components`.

- `apiRef?: Ref<VirtualListApi<Item> | null>;`
- `asChild: true;`
- `children: JSXElement;`
- `followBottom?: boolean | { threshold?: number; } | undefined;`
- `getKey: (item: Item, index: number) => string | number;`
- `items: readonly Item[];`
- `onScroll?: ((event: Event) => void) | undefined;`
- `overscan?: VirtualOverscan | undefined;`
- `ref?: Ref<HTMLElement>;`
- `rowComponent: VirtualListRowComponent<Item>;`
- `rowHeight: number;`
- `viewport?: "lg" | undefined;`

### `VirtualListProps`

Import from `@askrjs/themes/components`.

- `apiRef?: Ref<VirtualListApi<Item> | null>;`
- `asChild?: false | undefined;`
- `followBottom?: boolean | { threshold?: number; } | undefined;`
- `getKey: (item: Item, index: number) => string | number;`
- `items: readonly Item[];`
- `onScroll?: ((event: Event) => void) | undefined;`
- `overscan?: VirtualOverscan | undefined;`
- `ref?: Ref<HTMLElement>;`
- `rowComponent: VirtualListRowComponent<Item>;`
- `rowHeight: number;`
- `viewport?: "lg" | undefined;`

### `VirtualListRowComponentProps`

Import from `@askrjs/themes/components`.

- `index: number;`
- `isVisible: boolean;`
- `item: Item;`
- `rowKey: string;`

### `VirtualTableAsChildProps`

Import from `@askrjs/themes/components`.

- `apiRef?: Ref<VirtualTableApi<Row> | null>;`
- `asChild: true;`
- `children: JSXElement;`
- `columns: readonly VirtualTableColumn<Row>[];`
- `defaultSelectedRowKey?: string | null | undefined;`
- `getKey: (row: Row, index: number) => string | number;`
- `headerHeight: number;`
- `onRowClick?: ((row: Row, rowIndex: number, rowKey: string, event: MouseEvent) => void) | undefined;`
- `onScroll?: ((event: Event) => void) | undefined;`
- `onSelectedRowKeyChange?: ((next: string | null) => void) | undefined;`
- `overscan?: VirtualOverscan | undefined;`
- `ref?: Ref<HTMLElement>;`
- `rowHeight: number;`
- `rows: readonly Row[];`
- `selectedRowKey?: string | null | undefined;`
- `tableWidth?: "compact" | undefined;`
- `viewport?: "lg" | undefined;`

### `VirtualTableCellComponentProps`

Import from `@askrjs/themes/components`.

- `column: VirtualTableColumn<Row>;`
- `row: Row;`
- `rowIndex: number;`
- `rowKey: string;`
- `selected: boolean;`

### `VirtualTableProps`

Import from `@askrjs/themes/components`.

- `apiRef?: Ref<VirtualTableApi<Row> | null>;`
- `asChild?: false | undefined;`
- `columns: readonly VirtualTableColumn<Row>[];`
- `defaultSelectedRowKey?: string | null | undefined;`
- `getKey: (row: Row, index: number) => string | number;`
- `headerHeight: number;`
- `onRowClick?: ((row: Row, rowIndex: number, rowKey: string, event: MouseEvent) => void) | undefined;`
- `onScroll?: ((event: Event) => void) | undefined;`
- `onSelectedRowKeyChange?: ((next: string | null) => void) | undefined;`
- `overscan?: VirtualOverscan | undefined;`
- `ref?: Ref<HTMLElement>;`
- `rowHeight: number;`
- `rows: readonly Row[];`
- `selectedRowKey?: string | null | undefined;`
- `tableWidth?: "compact" | undefined;`
- `viewport?: "lg" | undefined;`

## Purpose

None of Alert, Badge, Empty, Skeleton, Spinner, or Stat ships a headless counterpart in `@askrjs/ui` — each lives only in the themes package, since their behavior amounts to static markup and styling rather than anything complex enough to justify a separate logic layer. Stat is the odd one out in a different way: it has no dedicated `@askrjs/themes/stat` subpath, so you reach it through the shared `@askrjs/themes/components` barrel instead of importing it on its own.

## Install and import

Alert, Badge, Empty, Skeleton, and Spinner each have their own themes subpath — `@askrjs/themes/alert`, `@askrjs/themes/badge`, `@askrjs/themes/empty`, `@askrjs/themes/skeleton`, `@askrjs/themes/spinner`. Stat has no subpath of its own: import `Stat`, `StatLabel`, `StatValue`, and `StatDescription` from the full `@askrjs/themes/components` barrel instead — or pull all six components from that same barrel if you'd rather have one import for the whole group.

## Live examples

The example branches across the states these components exist to cover — pending, failed, empty, and loaded — so you can see which one belongs in each branch rather than reaching for whichever is nearest. Stat comes from the `@askrjs/themes/components` barrel rather than its own subpath, and is otherwise a normal `Stat` / `StatLabel` / `StatValue` composition.

## Anatomy

Alert is a single component with `icon`, `title`, `description`, and `actions` slots plus a `titleAs` heading tag; Badge and Skeleton are similarly flat, single components with no compound parts. This group actually ships two different empty-state components, not one — don't conflate them: `Empty` is the compound one, with `EmptyHeader`, `EmptyMedia`, `EmptyTitle`, `EmptyDescription`, and `EmptyContent` slotting into an `Empty` wrapper (closer in shape to Card than to Alert or Badge), while `EmptyState` is a separate, single all-in-one component (`icon`/`title`/`titleAs`/`description`/`action` props, no compound parts of its own) for the common case where you don't need to hand-assemble the pieces. Spinner has no compound structure either; it's a themed wrapper around ProgressCircle's indeterminate presentation. Stat is compound too: a `Stat` wrapper composes with `StatLabel`, `StatValue`, and `StatDescription` children.

## State model

None of these six own any state — every one of them is presentational, driven entirely by the props you pass on each render, and that includes Stat. Alert accepts an `onDismiss` callback for a caller-owned dismiss button, but the decision to mount or unmount the alert is still yours; Alert doesn't track its own visibility internally.

## Keyboard and accessibility

Alert accepts a `dismissLabel` for the accessible name of its optional dismiss control, since that's the only interactive part across this group. Badge, Skeleton, Empty, Stat, and Spinner are non-interactive and have no keyboard behavior to test; because Spinner is effectively ProgressCircle's indeterminate look, give it a `label` so assistive tech gets something better than silence while it spins.

## Styling and tokens

Alert and Badge both take a `variant` prop that maps to theme tokens instead of requiring custom color CSS — Alert's set is `'default' | 'info' | 'success' | 'warning' | 'danger'`, Badge's is a bit wider with `'secondary'` and `'outline'` added. Skeleton takes explicit `width`/`height` so its placeholder shape matches the real content it's standing in for, and Spinner takes a `size` of `'sm' | 'md' | 'lg'`.

## API

Badge supports `asChild` to render as something other than a `span`, and Skeleton supports the same pattern for its wrapping `div`. Alert's props are `title`, `description`, `icon`, `actions`, `titleAs`, `dismissLabel`, `onDismiss`, and `variant`. `EmptyState` (the single all-in-one component, not the compound `Empty`/`EmptyHeader`/`EmptyMedia`/`EmptyTitle`/`EmptyDescription`/`EmptyContent` family) takes `icon`, `title`, `titleAs`, `description`, and `action`.

## Edge cases

Stat has no dedicated subpath, so a `@askrjs/themes/stat` import will fail — reach for `@askrjs/themes/components` instead, which is easy to miss if you're used to every other component here having its own subpath. Skeleton has no built-in timeout, so pair it with the real loading/error state next to it instead of letting it sit on screen indefinitely if a request stalls.

## Related pages

See Progress for a determinate alternative to Spinner's indeterminate look, and Toast and Sonner for time-boxed feedback instead of a persistent inline Alert.

## Documentation navigation

[Previous](https://askrjs.com/docs/components/toast-and-sonner/index.md) | [Next](https://askrjs.com/docs/charts/index.md)
