diff --git a/apps/docs/src/content/docs/rn-ui/changelog.mdx b/apps/docs/src/content/docs/rn-ui/changelog.mdx
index ae8a1bd..38b0c00 100644
--- a/apps/docs/src/content/docs/rn-ui/changelog.mdx
+++ b/apps/docs/src/content/docs/rn-ui/changelog.mdx
@@ -9,10 +9,30 @@ import ChangelogTimeline from '@/components/ChangelogTimeline.astro';
export const releases = [
{
- version: 'v0.3.0',
- date: '2026-08-25',
+ version: 'v0.3.1',
+ date: '2026-09-12',
tag: 'Latest Feature Release',
isLatest: true,
+ changes: [
+ {
+ type: 'feat',
+ text: 'Spinner & Loader Components: Dedicated high-performance loader component with 4 distinct animation variants (circular, ring, dots, bars), customizable speeds, size scales, semantic color tones, and descriptive labels.',
+ },
+ {
+ type: 'perf',
+ text: 'Ultra-Lightweight Skeleton with SkeletonGroup: Reduced SharedValues by 75%, removed native onLayout bridge listeners, and added SkeletonGroup for synchronized single-clock multi-skeleton screens with zero layout shift and safe unmount cleanup.',
+ },
+ {
+ type: 'fix',
+ text: 'Button & renderIcon Defensive Rendering: Safeguarded mixed children rendering to prevent un-wrapped text string errors in React Native and added automatic support for React forwardRef components.',
+ },
+ ],
+ },
+ {
+ version: 'v0.3.0',
+ date: '2026-08-25',
+ tag: 'Feature Release',
+ isLatest: false,
changes: [
{
type: 'feat',
diff --git a/apps/docs/src/content/docs/rn-ui/components/index.mdx b/apps/docs/src/content/docs/rn-ui/components/index.mdx
index b7b904f..d6b3cc1 100644
--- a/apps/docs/src/content/docs/rn-ui/components/index.mdx
+++ b/apps/docs/src/content/docs/rn-ui/components/index.mdx
@@ -2,12 +2,12 @@
title: Component Library
sidebar:
label: Overview
-description: Complete catalog of all 63 UI components available in @masumdev/rn-ui.
+description: Complete catalog of all 64 UI components available in @masumdev/rn-ui.
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
-Browse the complete catalog of 63 production-ready React Native & Expo components in `@masumdev/rn-ui`.
+Browse the complete catalog of 64 production-ready React Native & Expo components in `@masumdev/rn-ui`.
## Layout & Foundations
@@ -109,4 +109,5 @@ Browse the complete catalog of 63 production-ready React Native & Expo component
+
diff --git a/apps/docs/src/content/docs/rn-ui/components/spinner.mdx b/apps/docs/src/content/docs/rn-ui/components/spinner.mdx
new file mode 100644
index 0000000..f50b9db
--- /dev/null
+++ b/apps/docs/src/content/docs/rn-ui/components/spinner.mdx
@@ -0,0 +1,75 @@
+---
+title: Spinner
+description: High-performance animated loading spinner with circular arc, dual-ring, wave dots, and equalizer bar variants.
+sidebar:
+ badge:
+ text: "New"
+ variant: "tip"
+---
+
+import TypeTable from '@/components/TypeTable.astro';
+
+The **Spinner** component (also exported as `Loader`) provides fluid 60โ120fps UI thread loading indicators with 4 distinct animation variants, semantic design tokens, and optional descriptive labels.
+
+## Usage
+
+```tsx
+import React from 'react';
+import { Spinner, Box, Card, Text } from '@masumdev/rn-ui';
+
+export function SpinnerExample() {
+ return (
+
+ {/* 4 Animation Variants */}
+
+
+
+
+
+
+
+ {/* Sizes Scale (xs, sm, default, lg, xl) */}
+
+
+
+
+
+
+
+
+ {/* Spinner with Descriptive Label */}
+
+
+ );
+}
+```
+
+## Variants
+
+- **`circular`**: Classic high-performance SVG arc with background track ring.
+- **`ring`**: Elegant dual concentric rings with counter-rotating inner arc.
+- **`dots`**: Three phase-shifted pulsing wave dots.
+- **`bars`**: Four vertical soundwave equalizer bars.
+
+## Props API
+
+
diff --git a/apps/native/app/rn-ui/[id].tsx b/apps/native/app/rn-ui/[id].tsx
index 375b6df..4338b55 100644
--- a/apps/native/app/rn-ui/[id].tsx
+++ b/apps/native/app/rn-ui/[id].tsx
@@ -64,6 +64,7 @@ import {
SegmentedControlSection,
ChipSection,
SignaturePadSection,
+ SpinnerSection,
} from "../../components/rn-ui";
export default function RnUiComponentDetailScreen() {
@@ -210,6 +211,9 @@ export default function RnUiComponentDetailScreen() {
return ;
case "signature-pad":
return ;
+ case "spinner":
+ case "loader":
+ return ;
default:
return ;
diff --git a/apps/native/app/rn-ui/index.tsx b/apps/native/app/rn-ui/index.tsx
index 6245bba..552144f 100644
--- a/apps/native/app/rn-ui/index.tsx
+++ b/apps/native/app/rn-ui/index.tsx
@@ -431,6 +431,13 @@ export const CATALOG_CATEGORIES: ComponentCategory[] = [
description: "Content loading placeholder animation.",
tone: "primary",
},
+ {
+ id: "spinner",
+ name: "Spinner",
+ description:
+ "High-performance circular, dots, bars, and dual-ring loader spinners.",
+ tone: "primary",
+ },
{
id: "avatar",
name: "Avatar",
diff --git a/apps/native/components/rn-ui/index.ts b/apps/native/components/rn-ui/index.ts
index a36b6b7..620b1c4 100644
--- a/apps/native/components/rn-ui/index.ts
+++ b/apps/native/components/rn-ui/index.ts
@@ -56,4 +56,4 @@ export { SwipeableItemSection } from './sections/SwipeableItemSection';
export { SegmentedControlSection } from './sections/SegmentedControlSection';
export { ChipSection } from './sections/ChipSection';
export { SignaturePadSection } from './sections/SignaturePadSection';
-
+export { SpinnerSection } from './sections/SpinnerSection';
diff --git a/apps/native/components/rn-ui/sections/SkeletonSection.tsx b/apps/native/components/rn-ui/sections/SkeletonSection.tsx
index f7b40cd..41becdf 100644
--- a/apps/native/components/rn-ui/sections/SkeletonSection.tsx
+++ b/apps/native/components/rn-ui/sections/SkeletonSection.tsx
@@ -1,51 +1,388 @@
-import { Skeleton, Button, Card, Box, Text } from "@masumdev/rn-ui";
+import {
+ Avatar,
+ AvatarBadge,
+ AvatarFallback,
+ AvatarImage,
+ Badge,
+ Box,
+ Button,
+ Card,
+ Divider,
+ Skeleton,
+ SkeletonGroup,
+ Spinner,
+ Switch,
+ Text,
+} from "@masumdev/rn-ui";
+import {
+ Bookmark,
+ CheckCircle2,
+ Clock,
+ RefreshCw,
+ Share2,
+ Sparkles,
+ Star,
+ Users,
+} from "lucide-react-native";
import React from "react";
-import { Section, type RnUiSectionContext } from "../shared";
+import { Image, TouchableOpacity } from "react-native";
+import { SAMPLE_ASSETS, Section, type RnUiSectionContext } from "../shared";
-export function SkeletonSection({ ctx: _ctx }: { ctx: RnUiSectionContext }) {
+export function SkeletonSection({ ctx }: { ctx: RnUiSectionContext }) {
+ const { colors, icon } = ctx;
const [animated, setAnimated] = React.useState(true);
+ // Simulation state
+ const [isLoading, setIsLoading] = React.useState(false);
+ const [isFetching, setIsFetching] = React.useState(false);
+ const [liked, setLiked] = React.useState(false);
+ const [bookmarked, setBookmarked] = React.useState(false);
+
+ const simulateFetch = React.useCallback(() => {
+ setIsFetching(true);
+ setIsLoading(true);
+
+ const timer = setTimeout(() => {
+ setIsLoading(false);
+ setIsFetching(false);
+ }, 2000);
+
+ return () => clearTimeout(timer);
+ }, []);
+
return (
-
-
-
-
- Skeleton Shimmer
-
-
+
+ {/* Existing Skeleton Loaders Section */}
+
+
+
+
+ Skeleton Shimmer
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+ Diagonal Shimmer Direction
+
+
+
+
+ Horizontal Shimmer Direction
+
+
+
+
+
+
+
+ {/* Interactive Data Transition Simulation Section */}
+
+
+
+ {/* Header & Controls */}
+
+
+ Live Content Transition
+ {isLoading ? (
+
+
+
+ Fetching Data...
+
+
+ ) : (
+
+ Live Data Ready
+
+ )}
+
+
+ Demonstrating zero layout-shift (CLS) transition from placeholder skeleton to loaded components.
+
+
+ {/* Action Buttons / Controls */}
+
+
+
+
+
+ Force Skeleton
+
+ {
+ setIsLoading(val);
+ if (!val) setIsFetching(false);
+ }}
+ tone="primary"
+ />
+
-
-
- Diagonal Shimmer Direction
-
+
+
+ {/* Pattern 1: User Profile Card */}
+
+
+ 1. USER PROFILE CARD
+
+
+
+ {isLoading ? (
+ /* Skeleton State - Driven by a single shared clock via SkeletonGroup */
+
+
+
+
+
+
+
+
+
+
+
+
- Horizontal Shimmer Direction
-
+
+
+
+
+
+ {/* Stats pills */}
+
+
+
+
+
+
+ {/* Actions */}
+
+
+
+
+
+
+ ) : (
+ /* Loaded Data State */
+
+
+
+
+ {SAMPLE_ASSETS.avatarInitials}
+
+
+
+
+
+
+ {SAMPLE_ASSETS.avatarName}
+
+
+ PRO
+
+
+
+ @masumrpg ยท Lead Mobile Architect
+
+
+
+
+
+ Crafting typed cross-platform design systems, zero-overhead animations, and modular React Native libraries.
+
+
+ {/* Stats pills */}
+
+
+ 1.4k Followers
+
+
+ 63+ Components
+
+
+ 890 Stars
+
+
+
+ {/* Actions */}
+
+
+
+
+
+ )}
+
+
+
+ {/* Pattern 2: Media Feed Card */}
+
+
+ 2. MEDIA / FEED ARTICLE CARD
+
+
+
+ {isLoading ? (
+ /* Skeleton State - Driven by SkeletonGroup */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ /* Loaded Data State */
+
+
+
+
+
+ REACT NATIVE
+
+
+
+
+ 4 min read
+
+
+
+
+
+ Zero-Shift Loading States with Skeleton Shimmer
+
+
+
+
+
+
+ {SAMPLE_ASSETS.avatarInitials}
+
+
+ {"Ma'sum ยท 2h ago"}
+
+
+
+
+ setLiked(!liked)} activeOpacity={0.7}>
+
+
+ setBookmarked(!bookmarked)} activeOpacity={0.7}>
+
+
+
+
+
+
+
+
+ )}
+
+
-
-
-
+
+
+
);
}
diff --git a/apps/native/components/rn-ui/sections/SpinnerSection.tsx b/apps/native/components/rn-ui/sections/SpinnerSection.tsx
new file mode 100644
index 0000000..712ca42
--- /dev/null
+++ b/apps/native/components/rn-ui/sections/SpinnerSection.tsx
@@ -0,0 +1,277 @@
+import {
+ Badge,
+ Box,
+ Button,
+ Card,
+ Spinner,
+ type SpinnerSize,
+ type SpinnerSpeed,
+ type SpinnerVariant,
+ Text,
+} from "@masumdev/rn-ui";
+import { RotateCcw } from "lucide-react-native";
+import React from "react";
+import { Section, type RnUiSectionContext } from "../shared";
+
+export function SpinnerSection({ ctx }: { ctx: RnUiSectionContext }) {
+ const { colors, icon } = ctx;
+
+ const [variant, setVariant] = React.useState("circular");
+ const [size, setSize] = React.useState("default");
+ const [speed, setSpeed] = React.useState("normal");
+ const [animated, setAnimated] = React.useState(true);
+
+ // Card overlay simulation
+ const [isOverlayLoading, setIsOverlayLoading] = React.useState(false);
+
+ const triggerOverlaySync = () => {
+ setIsOverlayLoading(true);
+ setTimeout(() => {
+ setIsOverlayLoading(false);
+ }, 2500);
+ };
+
+ return (
+
+
+ {/* Interactive Playground Card */}
+
+
+
+
+ Live Spinner Playground
+
+
+
+
+ High-performance 60-120fps UI thread loaders with zero memory leaks and safe unmount cleanup.
+
+
+ {/* Live Preview Box */}
+
+
+
+
+ {/* Variant Selector */}
+
+
+ Variant
+
+
+ {(["circular", "ring", "dots", "bars"] as const).map((v) => (
+
+ ))}
+
+
+
+ {/* Size Selector */}
+
+
+ Size
+
+
+ {(["xs", "sm", "default", "lg", "xl"] as const).map((s) => (
+
+ ))}
+
+
+
+ {/* Speed Selector */}
+
+
+ Speed
+
+
+ {(["slow", "normal", "fast"] as const).map((spd) => (
+
+ ))}
+
+
+
+
+
+ {/* All Variants Gallery */}
+
+
+
+ Loader Variants
+
+
+ Four distinct animation styles for different UX context and hierarchies.
+
+
+
+
+
+
+ Circular Arc
+
+
+
+
+
+
+ Dual Ring
+
+
+
+
+
+
+ Wave Dots
+
+
+
+
+
+
+ Sound Bars
+
+
+
+
+
+
+ {/* Semantic Tones */}
+
+
+
+ Semantic Color Tones
+
+
+ Inherits full design tokens from the active theme.
+
+
+
+ {(["primary", "secondary", "accent", "success", "warning", "danger", "info"] as const).map((t) => (
+
+
+
+ {t}
+
+
+ ))}
+
+
+
+
+ {/* Card Overlay Loading Simulation */}
+
+
+
+
+ Card Overlay Simulation
+
+
+
+
+
+
+
+ Ma'sum Cloud Storage
+
+
+ 48 mobile packages, 227 verified clean files, 1.4k followers connected.
+
+
+
+ Connected
+
+
+ v0.3.0
+
+
+
+
+ {/* Loading Overlay */}
+ {isOverlayLoading && (
+
+
+
+ )}
+
+
+
+
+
+ );
+}
diff --git a/packages/rn-ui/CHANGELOG.md b/packages/rn-ui/CHANGELOG.md
new file mode 100644
index 0000000..a85dc93
--- /dev/null
+++ b/packages/rn-ui/CHANGELOG.md
@@ -0,0 +1,40 @@
+# Changelog
+
+All notable changes to **@masumdev/rn-ui** will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [0.3.1] - 2026-09-12
+
+### Added
+- **Spinner & Loader Components**:
+ - Brand-new dedicated `Spinner` component (also exported as `Loader`) powered by `react-native-reanimated` with 60โ120fps UI thread execution.
+ - Supports 4 visual animation variants: `circular` (high-performance SVG arc), `ring` (dual concentric reverse-spinning rings), `dots` (three phase-shifted pulsing wave dots), and `bars` (vertical soundwave equalizer bars).
+ - Configurable speeds (`slow`, `normal`, `fast`, or custom ms duration), size scales (`xs`, `sm`, `default`, `lg`, `xl`, or numeric pixel size), semantic color tones (`primary`, `secondary`, `accent`, `success`, `warning`, `danger`, `info`), and optional descriptive labels with flexible placement (`bottom`, `top`, `left`, `right`).
+ - Added interactive showcase demo in `apps/native` playground with live playground, variant gallery, and card overlay simulation.
+ - Added complete documentation and prop table in `apps/docs`.
+
+### Optimized
+- **Ultra-Lightweight Skeleton & SkeletonGroup**:
+ - Reduced memory footprint by 75% (from 4 SharedValues per skeleton to 1 single `progress` SharedValue).
+ - Cut animation CPU loops by 50% by deriving both subtle pulse and shimmer wave from a unified clock.
+ - Eliminated `onLayout` bridge round-trips by computing sweep distances geometrically based on viewport width.
+ - Added `` container to drive arbitrary numbers of child skeletons from a single shared UI thread clock (O(1) overhead regardless of skeleton count).
+ - Guaranteed safe unmount and destroy cleanup via `cancelAnimation` to prevent worklet collision or frame drops when transitioning from skeleton to live data.
+
+### Fixed
+- **Button Defensive Rendering & renderIcon Safety**:
+ - Enhanced `