Add Folder Animation component and registry entries

Introduces the Folder Animation component for Carbon, including documentation, registry JSON files, and demo. Updates related docs, registry, and scripts to support the new component. Also refines category and description for Native User Card components and updates registry to remove deprecated native components.
This commit is contained in:
moumensoliman 2026-01-24 22:28:08 +02:00
parent 6c135fe25f
commit 4eed926554
67 changed files with 1454 additions and 721 deletions

View file

@ -573,14 +573,20 @@ export default function AnimationDetailPageClient({
]);
const installId = React.useMemo(() => {
if (
component.category === "native" ||
(component.availableIn && component.availableIn.length > 1)
) {
const availableIn = component.availableIn || [];
const isMultiLibrary =
component.category === "native" || availableIn.length > 1;
if (isMultiLibrary) {
// Carbon-only components should always install the carbon variant,
// even if the UI library is shadcnui/baseui.
if (availableIn.includes("carbon") && !availableIn.includes(selectedLibrary)) {
return `${component.id}-carbon`;
}
return `${component.id}-${selectedLibrary}`;
}
return component.id;
}, [component.id, component.category, selectedLibrary]);
}, [component.id, component.category, component.availableIn, selectedLibrary]);
return (
<main className="flex h-full flex-1 flex-col overflow-hidden">

View file

@ -2,14 +2,14 @@
> Production-ready UI components, blocks, and pages built on top of shadcn/ui and Framer Motion.
**Last Updated:** 2026-01-23T21:11:13.445Z
**Last Updated:** 2026-01-24T20:17:43.190Z
## Table of Contents
- Components (160 items)
- Components (161 items)
- Blocks (74 items)
- Pages (23 items)
- UI Elements (19 items)
- UI Elements (20 items)
### Components
@ -37,6 +37,8 @@
- [Glass Wallet Card](https://ui.tripled.work/components/glass-wallet-card-shadcnui): Glassmorphism crypto wallet card with balance, trend, and action buttons
- [Hover Expand Card](https://ui.tripled.work/components/hover-expand-card-baseui): Card that lifts and expands on hover (Base UI)
- [Hover Expand Card](https://ui.tripled.work/components/hover-expand-card-shadcnui): Card that lifts and expands on hover
- [Native User Card](https://ui.tripled.work/components/native-user-card-baseui): Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)
- [Native User Card](https://ui.tripled.work/components/native-user-card-shadcnui): Compact user profile card with avatar, name, handle, and action button with spring animations
- [Project Card](https://ui.tripled.work/components/project-card-baseui): Glassmorphism project card with links, tags, and hover effects (Base UI)
- [Project Card](https://ui.tripled.work/components/project-card-shadcnui): Glassmorphism project card with links, tags, and hover effects
- [Theater Ticket](https://ui.tripled.work/components/theater-ticket-baseui): Cinematic theater ticket with rip effect and barcode (Base UI)
@ -133,6 +135,7 @@
- [Wizard Form](https://ui.tripled.work/components/wizard-form-shadcnui): Multi-step wizard form with animated transitions, validation, and progress tracking
- [Bottom Modal](https://ui.tripled.work/components/bottom-modal): Cute bottom-centered modal with smooth slide-up animation and glassmorphism design
- [Folder Animation](https://ui.tripled.work/components/folder-animation-carbon): Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.
- [Native Avatar Expand](https://ui.tripled.work/components/native-avatar-expand-baseui): Avatar component that expands to reveal the name on click with smooth animations. (Base UI)
- [Native Avatar Expand](https://ui.tripled.work/components/native-avatar-expand-shadcnui): Avatar component that expands to reveal the name on click with smooth animations.
- [Native Avatar With Name](https://ui.tripled.work/components/native-avatar-with-name-baseui): Avatar component that displays a name tooltip on hover with directional animations. (Base UI)
@ -188,8 +191,6 @@
- [Native Typewriter](https://ui.tripled.work/components/native-typewriter): Typewriter effect with speed control, looping, and blinking cursor.
- [Native Typewriter](https://ui.tripled.work/components/native-typewriter-baseui): Typewriter effect with speed control, looping, and blinking cursor. (Base UI)
- [Native Typewriter](https://ui.tripled.work/components/native-typewriter-shadcnui): Typewriter effect with speed control, looping, and blinking cursor.
- [Native User Card](https://ui.tripled.work/components/native-user-card-baseui): Compact user profile card with avatar, name, handle, and action button with spring animations. (Base UI)
- [Native User Card](https://ui.tripled.work/components/native-user-card-shadcnui): Compact user profile card with avatar, name, handle, and action button with spring animations.
- [Native Verified Badge](https://ui.tripled.work/components/native-verified-badge-baseui): Verified badge component with multiple variants, sizes, and styles including outline and shield designs. (Base UI)
- [Native Verified Badge](https://ui.tripled.work/components/native-verified-badge-shadcnui): Verified badge component with multiple variants, sizes, and styles including outline and shield designs.
- [Social Login Button](https://ui.tripled.work/components/social-login-button-baseui): A set of animated social login buttons for major platforms (Github, Google, X, etc.) with various effects. (Base UI)
@ -341,6 +342,7 @@
- [Animated Quote Block](https://ui.tripled.work/components/animated-quote-block-shadcnui): Quote that types itself in, pauses, then subtly breathes
- [Dynamic Tag Cloud](https://ui.tripled.work/components/dynamic-tag-cloud-shadcnui): Floating cluster of tags that drift and rearrange when hovered
- [Floating Info Panel](https://ui.tripled.work/components/floating-info-panel-shadcnui): Info tooltip that drifts up/down while fading in/out intermittently
- [Folder Animation](https://ui.tripled.work/components/folder-animation): Animated folder card with motion blur effect, perfect for showcasing file operations or loading states
- [Holographic Wall](https://ui.tripled.work/components/holographic-wall-shadcnui): Black wall with Pharaonic hieroglyphs and golden cursor light reflection
- [Liquid Cursor](https://ui.tripled.work/components/liquid-cursor-shadcnui): A liquid-like cursor effect that mixes colors on movement
- [Spotlight Section](https://ui.tripled.work/components/spotlight-section-shadcnui): Container where mouse creates soft radial spotlight following cursor

View file

@ -0,0 +1,124 @@
---
title: Folder Animation
description: Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.
component: true
---
```tsx
"use client"
import * as React from "react"
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx"
export function FolderAnimationDemo() {
return (
<FolderAnimation />
)
}
```
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add @uitripled/folder-animation-carbon
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="folder-animation-carbon" title="@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx"
```
```tsx showLineNumbers
<FolderAnimation />
```
## Component Details
- **Category**: native
### Technical Specifications
**Dependencies**:
- `framer-motion`
- `react`
This component uses **Framer Motion** for animations and motion effects.
## Customization
This component can be customized by modifying the following:
- **Styling**: The component uses Tailwind CSS for styling. Customize colors, spacing, and other design tokens through Tailwind classes.
- **Props**: Pass custom props to configure the component's behavior and appearance.
- **Variants**: Create custom variants by extending the component's base styles.
## Accessibility
The component follows accessibility best practices:
- Proper ARIA labels and roles
- Keyboard navigation support
- Screen reader compatibility
- Focus management
## Examples
### Basic Example
```tsx
"use client"
import * as React from "react"
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx"
export function BasicExample() {
return (
<FolderAnimation />
)
}
```
## API Reference
This component is part of the UI TripleD component library, a collection of production-ready components built with Framer Motion, shadcn/ui, and Tailwind CSS.
## Best Practices
1. **Performance**: Consider lazy loading if used in large lists or below-the-fold content.
2. **Theming**: Ensure your theme configuration includes the necessary CSS variables.
3. **Testing**: Test keyboard navigation and screen reader compatibility.
4. **Customization**: Use props for configuration rather than modifying source code.
## Related Components
No related components.

View file

@ -0,0 +1,124 @@
---
title: Folder Animation
description: Animated folder card with motion blur effect, perfect for showcasing file operations or loading states
component: true
---
```tsx
"use client"
import * as React from "react"
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx"
export function FolderAnimationDemo() {
return (
<FolderAnimation />
)
}
```
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add @uitripled/folder-animation
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="folder-animation" title="@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx"
```
```tsx showLineNumbers
<FolderAnimation />
```
## Component Details
- **Category**: decorative
### Technical Specifications
**Dependencies**:
- `framer-motion`
- `react`
This component uses **Framer Motion** for animations and motion effects.
## Customization
This component can be customized by modifying the following:
- **Styling**: The component uses Tailwind CSS for styling. Customize colors, spacing, and other design tokens through Tailwind classes.
- **Props**: Pass custom props to configure the component's behavior and appearance.
- **Variants**: Create custom variants by extending the component's base styles.
## Accessibility
The component follows accessibility best practices:
- Proper ARIA labels and roles
- Keyboard navigation support
- Screen reader compatibility
- Focus management
## Examples
### Basic Example
```tsx
"use client"
import * as React from "react"
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx"
export function BasicExample() {
return (
<FolderAnimation />
)
}
```
## API Reference
This component is part of the UI TripleD component library, a collection of production-ready components built with Framer Motion, shadcn/ui, and Tailwind CSS.
## Best Practices
1. **Performance**: Consider lazy loading if used in large lists or below-the-fold content.
2. **Theming**: Ensure your theme configuration includes the necessary CSS variables.
3. **Testing**: Test keyboard navigation and screen reader compatibility.
4. **Customization**: Use props for configuration rather than modifying source code.
## Related Components
No related components.

View file

@ -1,6 +1,6 @@
---
title: Native User Card
description: Compact user profile card with avatar, name, handle, and action button with spring animations. (Base UI)
description: Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)
component: true
---
@ -68,7 +68,7 @@ import { NativeUserCard } from "@uitripled/react-baseui/src/components/native/na
## Component Details
- **Category**: native
- **Category**: cards
### Technical Specifications

View file

@ -1,6 +1,6 @@
---
title: Native User Card
description: Compact user profile card with avatar, name, handle, and action button with spring animations.
description: Compact user profile card with avatar, name, handle, and action button with spring animations
component: true
---
@ -62,7 +62,7 @@ import { NativeUserCard } from "@uitripled/react-shadcn/src/components/native/na
## Component Details
- **Category**: native
- **Category**: cards
### Technical Specifications

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,7 @@
"name": "native-user-card-baseui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations. (Base UI)",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)",
"registryDependencies": [
"button"
],

View file

@ -3,7 +3,7 @@
"name": "native-user-card-shadcnui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations.",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations",
"dependencies": [
"framer-motion",
"react"

View file

@ -1315,7 +1315,7 @@
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/components/stocks-dashboard/dashboard.tsx",
"path": "@uitripled/react-baseui/src/components/stocks-dashboard/dashboard-baseui.tsx",
"type": "registry:block",
"target": "components/uitripled/dashboard-baseui.tsx"
}
@ -1900,6 +1900,46 @@
"category": "components",
"subcategory": "modal"
},
{
"name": "folder-animation",
"type": "registry:ui",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:ui",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "decorative",
"subcategory": null
},
{
"name": "folder-animation-carbon",
"type": "registry:component",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "footer-block-baseui",
"type": "registry:block",
@ -3652,7 +3692,7 @@
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/native/native-flip-text-baseui.tsx",
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon-baseui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-flip-text-baseui.tsx"
}
@ -4472,7 +4512,7 @@
"name": "native-user-card-baseui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations. (Base UI)",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)",
"registryDependencies": [
"button"
],
@ -4487,14 +4527,14 @@
"target": "components/uitripled/native-user-card-baseui.tsx"
}
],
"category": "native",
"category": "cards",
"subcategory": null
},
{
"name": "native-user-card-shadcnui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations.",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations",
"registryDependencies": [],
"dependencies": [
"framer-motion",
@ -4507,7 +4547,7 @@
"target": "components/uitripled/native-user-card-shadcnui.tsx"
}
],
"category": "native",
"category": "cards",
"subcategory": null
},
{

View file

@ -1315,7 +1315,7 @@
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/components/stocks-dashboard/dashboard.tsx",
"path": "@uitripled/react-baseui/src/components/stocks-dashboard/dashboard-baseui.tsx",
"type": "registry:block",
"target": "components/uitripled/dashboard-baseui.tsx"
}
@ -1900,6 +1900,46 @@
"category": "components",
"subcategory": "modal"
},
{
"name": "folder-animation",
"type": "registry:ui",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:ui",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "decorative",
"subcategory": null
},
{
"name": "folder-animation-carbon",
"type": "registry:component",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "footer-block-baseui",
"type": "registry:block",
@ -4472,7 +4512,7 @@
"name": "native-user-card-baseui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations. (Base UI)",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)",
"registryDependencies": [
"button"
],
@ -4487,14 +4527,14 @@
"target": "components/uitripled/native-user-card-baseui.tsx"
}
],
"category": "native",
"category": "cards",
"subcategory": null
},
{
"name": "native-user-card-shadcnui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations.",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations",
"registryDependencies": [],
"dependencies": [
"framer-motion",
@ -4507,7 +4547,7 @@
"target": "components/uitripled/native-user-card-shadcnui.tsx"
}
],
"category": "native",
"category": "cards",
"subcategory": null
},
{

View file

@ -1,25 +1,37 @@
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const ROOT_DIR = path.join(__dirname, "../../..");
const SOURCE_REGISTRY_PATH = path.join(
__dirname,
"../../../packages/registry/registry.json"
ROOT_DIR,
"packages/registry/registry.json"
);
const DEST_REGISTRY_PATH = path.join(__dirname, "../registry.json");
function generateRegistry() {
try {
execSync("pnpm registry:generate", {
cwd: ROOT_DIR,
stdio: "inherit",
});
} catch (error) {
console.error("❌ Failed to generate registry files:", error);
}
}
function syncRegistry() {
try {
console.log("🔄 Syncing registry.json from packages/registry...");
generateRegistry();
if (!fs.existsSync(SOURCE_REGISTRY_PATH)) {
console.error(
`❌ Source registry file not found at: ${SOURCE_REGISTRY_PATH}`
);
console.log(
"⚠️ Ensure you have run 'pnpm registry:generate' or built the registry package."
"⚠️ Ensure you have run 'pnpm registry:generate' from the repo root."
);
// Do not exit with error to avoid crashing dev server if race condition,
// but warn heavily. User might need to build registry once.
return;
}

View file

@ -7,9 +7,9 @@
"dev": "turbo run dev",
"lint": "turbo run lint",
"type-check": "turbo run type-check",
"registry:generate": "turbo run registry:generate",
"registry:sync": "turbo run registry:sync",
"registry:validate": "turbo run registry:validate",
"registry:generate": "pnpm dlx tsx packages/scripts/src/sync-registry.ts && pnpm dlx tsx packages/scripts/src/generate-registry-files.ts",
"registry:sync": "node apps/docs/scripts/sync-registry.js",
"registry:validate": "pnpm dlx tsx packages/scripts/src/validate-registry.ts",
"changeset": "changeset",
"version-packages": "changeset version",
"release": "turbo run build --filter=@uitripled/* && changeset publish"

View file

@ -0,0 +1,163 @@
"use client";
import { Button } from "@uitripled/react-shadcn/ui/button";
import { FileText, Folder, Image, Music } from "lucide-react";
import { FolderAnimation } from "../folder-animation-carbon";
const RESPONSIVE_WIDTH = "w-full max-w-md";
export function FolderAnimationDefault() {
return (
<FolderAnimation className={RESPONSIVE_WIDTH}>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Organizing Your Files</h3>
<p className="text-sm text-muted-foreground">
Watch as files seamlessly move through your workspace with smooth
motion blur effects.
</p>
</div>
</FolderAnimation>
);
}
export function FolderAnimationFast() {
return (
<FolderAnimation className={RESPONSIVE_WIDTH} animationDuration={2}>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Quick Transfer</h3>
<p className="text-sm text-muted-foreground">
Faster animation for quick file operations.
</p>
</div>
</FolderAnimation>
);
}
export function FolderAnimationSlow() {
return (
<FolderAnimation className={RESPONSIVE_WIDTH} animationDuration={6}>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Careful Handling</h3>
<p className="text-sm text-muted-foreground">
Slower animation for detailed file processing.
</p>
</div>
</FolderAnimation>
);
}
export function FolderAnimationCustomIcon() {
return (
<FolderAnimation
className={RESPONSIVE_WIDTH}
folderIcon={
<div className="relative">
<div className="w-24 h-24 bg-gradient-to-br from-blue-500 to-blue-700 rounded-xl flex items-center justify-center shadow-2xl">
<FileText className="w-12 h-12 text-white" />
</div>
</div>
}
>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Document Processing</h3>
<p className="text-sm text-muted-foreground">
Custom icon for document-specific operations.
</p>
</div>
</FolderAnimation>
);
}
export function FolderAnimationImageIcon() {
return (
<FolderAnimation
className={RESPONSIVE_WIDTH}
folderIcon={
<div className="relative">
<div className="w-28 h-24 bg-gradient-to-br from-purple-500 to-pink-500 rounded-xl flex items-center justify-center shadow-2xl overflow-hidden">
<Image className="w-12 h-12 text-white" />
<div className="absolute inset-0 bg-gradient-to-t from-transparent to-white/20" />
</div>
</div>
}
>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Image Gallery</h3>
<p className="text-sm text-muted-foreground">
Organizing your photos with style.
</p>
</div>
</FolderAnimation>
);
}
export function FolderAnimationMusicIcon() {
return (
<FolderAnimation
className={RESPONSIVE_WIDTH}
folderIcon={
<div className="relative">
<div className="w-24 h-24 bg-gradient-to-br from-green-500 to-emerald-600 rounded-full flex items-center justify-center shadow-2xl">
<Music className="w-10 h-10 text-white" />
</div>
</div>
}
animationDuration={3}
>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Music Library</h3>
<p className="text-sm text-muted-foreground">
Your audio files in motion.
</p>
</div>
</FolderAnimation>
);
}
export function FolderAnimationWithActions() {
return (
<FolderAnimation className={RESPONSIVE_WIDTH}>
<div className="space-y-4">
<div className="md:flex items-center gap-3 flex-col md:flex-row space-y-2 md:space-y-0">
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center">
<Folder className="w-5 h-5 text-primary" />
</div>
<div className="flex-1">
<h3 className="font-semibold">File Transfer in Progress</h3>
<p className="text-xs text-muted-foreground">
Moving 24 files to destination
</p>
</div>
</div>
<div className="flex w-full items-center flex-col md:flex-row gap-2">
<Button size="sm">
View Details
</Button>
</div>
</div>
</FolderAnimation>
);
}
export function FolderAnimationNoFooter() {
return <FolderAnimation className={RESPONSIVE_WIDTH} />;
}
export function FolderAnimationDemo() {
return (
<div className="flex flex-col gap-12 w-full">
<div className="space-y-2">
<h3 className="font-semibold text-muted-foreground">Default</h3>
<FolderAnimationDefault />
</div>
<div className="space-y-2">
<h3 className="font-semibold text-muted-foreground">Custom Icon</h3>
<FolderAnimationCustomIcon />
</div>
<div className="space-y-2">
<h3 className="font-semibold text-muted-foreground">With Actions</h3>
<FolderAnimationWithActions />
</div>
</div>
);
}

View file

@ -0,0 +1,226 @@
"use client";
import { cn } from "@uitripled/utils";
import {
motion,
useAnimationControls,
useReducedMotion,
} from "framer-motion";
import { type ReactNode, useState, useCallback, useEffect, useRef } from "react";
interface FolderAnimationProps {
/**
* Duration of the animation cycle in seconds.
* Default: 3
*/
animationDuration?: number;
/**
* Custom folder icon to display. If not provided, a default folder icon is rendered.
*/
folderIcon?: ReactNode;
/**
* Content to display in the card footer.
*/
children?: ReactNode;
/**
* Additional CSS classes for the container.
*/
className?: string;
/**
* Accessible label for the animation area.
*/
ariaLabel?: string;
}
export function FolderAnimation({
animationDuration = 3,
folderIcon,
children,
className,
ariaLabel = "Animated folder illustration",
}: FolderAnimationProps) {
const [isHovered, setIsHovered] = useState(false);
const prefersReducedMotion = useReducedMotion();
const controls = useAnimationControls();
const blurControls = useAnimationControls();
const isAnimatingRef = useRef(false);
const shouldStopRef = useRef(false);
const handleMouseEnter = useCallback(() => setIsHovered(true), []);
const handleMouseLeave = useCallback(() => setIsHovered(false), []);
const handleFocus = useCallback(() => setIsHovered(true), []);
const handleBlur = useCallback(() => setIsHovered(false), []);
// Animation sequence: center → right → (wrap to left) → center → repeat
const runAnimation = useCallback(async () => {
if (prefersReducedMotion) return;
isAnimatingRef.current = true;
shouldStopRef.current = false;
while (!shouldStopRef.current) {
// Phase 1: Center to right (exit right with blur)
await Promise.all([
controls.start({
x: "150%",
opacity: [1, 1, 0],
transition: {
duration: animationDuration / 2,
ease: "easeIn",
times: [0, 0.7, 1],
},
}),
blurControls.start({
filter: ["blur(0px)", "blur(0px)", "blur(8px)", "blur(16px)"],
transition: {
duration: animationDuration / 2,
ease: "easeIn",
times: [0, 0.5, 0.75, 1],
},
}),
]);
if (shouldStopRef.current) break;
// Instantly move to left (off-screen)
await controls.set({ x: "-150%", opacity: 0 });
await blurControls.set({ filter: "blur(16px)" });
if (shouldStopRef.current) break;
// Phase 2: Left to center (enter from left, deblur)
await Promise.all([
controls.start({
x: "0%",
opacity: [0, 1, 1],
transition: {
duration: animationDuration / 2,
ease: "easeOut",
times: [0, 0.3, 1],
},
}),
blurControls.start({
filter: ["blur(16px)", "blur(8px)", "blur(0px)", "blur(0px)"],
transition: {
duration: animationDuration / 2,
ease: "easeOut",
times: [0, 0.25, 0.5, 1],
},
}),
]);
if (shouldStopRef.current) break;
// Brief pause at center
await new Promise((resolve) => setTimeout(resolve, 400));
}
isAnimatingRef.current = false;
}, [controls, blurControls, animationDuration, prefersReducedMotion]);
// Return to center smoothly
const returnToCenter = useCallback(async () => {
shouldStopRef.current = true;
await Promise.all([
controls.start({
x: "0%",
opacity: 1,
transition: {
duration: 0.5,
ease: [0.25, 0.1, 0.25, 1], // cubic-bezier for smooth deceleration
},
}),
blurControls.start({
filter: "blur(0px)",
transition: {
duration: 0.3,
ease: "easeOut",
},
}),
]);
isAnimatingRef.current = false;
}, [controls, blurControls]);
useEffect(() => {
if (isHovered && !prefersReducedMotion) {
runAnimation();
} else {
returnToCenter();
}
}, [isHovered, prefersReducedMotion, runAnimation, returnToCenter]);
// Set initial position
useEffect(() => {
controls.set({ x: "0%", opacity: 1 });
blurControls.set({ filter: "blur(0px)" });
}, [controls, blurControls]);
return (
<div className={cn(className)}>
{/* Card Container */}
<div className="bg-card p-2 rounded-lg overflow-hidden w-full border border-border">
{/* Animation Area */}
<div
className="relative w-full h-64 bg-muted overflow-hidden flex items-center justify-center rounded-lg cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onFocus={handleFocus}
onBlur={handleBlur}
tabIndex={0}
role="img"
aria-label={ariaLabel}
>
{/* Animated Icon/Folder */}
<motion.div
animate={controls}
className="absolute"
style={{ willChange: "transform, opacity" }}
>
<motion.div
animate={blurControls}
className="relative"
style={{ willChange: "filter" }}
>
{folderIcon ? (
<div className="flex items-center justify-center">{folderIcon}</div>
) : (
<div className="relative w-28 h-24">
{/* Folder Back */}
<div className="absolute inset-0 bg-primary/10 rounded-lg border border-primary/20">
{/* Tab */}
</div>
{/* Files inside */}
<div className="absolute bottom-2 left-2 right-2 h-20 bg-background border border-border rounded shadow-sm transform -rotate-3 origin-bottom-left flex flex-col p-2 gap-1.5">
<div className="w-8 h-1 bg-muted rounded-full" />
<div className="w-full h-1 bg-muted/50 rounded-full" />
<div className="w-16 h-1 bg-muted/50 rounded-full" />
</div>
<div className="absolute bottom-2 left-2 right-2 h-20 bg-background border border-border rounded shadow-sm transform rotate-3 origin-bottom-right z-10 flex flex-col p-2 gap-1.5">
<div className="flex gap-2 items-center mb-1">
<div className="w-4 h-4 bg-primary/10 rounded-full" />
<div className="w-10 h-1 bg-muted rounded-full" />
</div>
<div className="w-full h-1 bg-muted/50 rounded-full" />
<div className="w-3/4 h-1 bg-muted/50 rounded-full" />
</div>
{/* Folder Front */}
<div className="absolute bottom-0 inset-x-0 h-14 bg-gradient-to-br from-primary/20 to-primary/5 backdrop-blur-md rounded-lg border-t border-white/20 border-x border-primary/10 shadow-lg z-20 flex items-center justify-center">
<div className="w-8 h-1 bg-primary/20 rounded-full" />
</div>
</div>
)}
</motion.div>
</motion.div>
</div>
{/* Card Footer */}
{children && <div className="p-3 mt-5">{children}</div>}
</div>
</div>
);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -14,7 +14,7 @@
"files": [
{
"path": "@uitripled/react-baseui/src/components/sections/feature-grid-section-baseui.tsx",
"content": "\"use client\";\n\nimport { motion, useInView, type Variants } from \"framer-motion\";\nimport { Code, Globe, Lock, Shield, Sparkles, Zap } from \"lucide-react\";\nimport { useRef } from \"react\";\n\nconst features = [\n {\n icon: Code,\n title: \"Developer Friendly\",\n description: \"Built with TypeScript and modern React patterns\",\n },\n {\n icon: Zap,\n title: \"Lightning Fast\",\n description: \"Optimized animations that never lag\",\n },\n {\n icon: Shield,\n title: \"Production Ready\",\n description: \"Tested and ready for your next project\",\n },\n {\n icon: Globe,\n title: \"Responsive\",\n description: \"Works perfectly on all devices\",\n },\n {\n icon: Lock,\n title: \"Secure\",\n description: \"Built with security best practices\",\n },\n {\n icon: Sparkles,\n title: \"Modern\",\n description: \"Using the latest web technologies\",\n },\n];\n\nexport function FeatureGridSectionBaseui() {\n const ref = useRef(null);\n const isInView = useInView(ref, { once: true, margin: \"-50px\" });\n\n const containerVariants: Variants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: 0.1,\n delayChildren: 0.2,\n },\n },\n };\n\n const itemVariants: Variants = {\n hidden: { opacity: 0, y: 30, scale: 0.9 },\n visible: {\n opacity: 1,\n y: 0,\n scale: 1,\n transition: {\n type: \"spring\",\n stiffness: 100,\n damping: 15,\n },\n },\n };\n\n return (\n <div ref={ref} className=\"w-full px-4 py-16\">\n <div className=\"mx-auto max-w-6xl\">\n <motion.div\n initial={{ opacity: 0, y: 30 }}\n animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}\n transition={{ duration: 0.6 }}\n className=\"mb-12 text-center\"\n >\n <h2 className=\"mb-4 text-3xl font-bold sm:text-4xl md:text-5xl\">\n Why Choose Us\n </h2>\n <p className=\"text-sm text-foreground/70 sm:text-base md:text-lg\">\n Everything you need to build amazing applications\n </p>\n </motion.div>\n\n <motion.div\n variants={containerVariants}\n initial=\"hidden\"\n animate={isInView ? \"visible\" : \"hidden\"}\n className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\"\n >\n {features.map((feature, index) => {\n const Icon = feature.icon;\n return (\n <motion.div key={feature.title} variants={itemVariants}>\n <div className=\"h-full rounded-lg border border-border bg-card text-card-foreground shadow-sm transition-all hover:shadow-lg\">\n <div className=\"flex flex-col space-y-1.5 p-6\">\n <motion.div\n initial={{ opacity: 0, scale: 0.8, rotate: -60 }}\n animate={\n isInView\n ? { opacity: 1, scale: 1, rotate: 0 }\n : { opacity: 0, scale: 0.8, rotate: -60 }\n }\n transition={{\n delay: index * 0.1 + 0.3,\n type: \"spring\",\n stiffness: 120,\n damping: 18,\n mass: 0.6,\n }}\n className=\"mb-4 inline-flex\"\n >\n <Icon\n className=\"h-6 w-6 text-muted-foreground\"\n aria-hidden=\"true\"\n />\n </motion.div>\n <h3 className=\"text-xl font-semibold leading-none tracking-tight\">\n {feature.title}\n </h3>\n </div>\n <div className=\"p-6 pt-0\">\n <p className=\"text-base text-muted-foreground\">\n {feature.description}\n </p>\n </div>\n </div>\n </motion.div>\n );\n })}\n </motion.div>\n </div>\n </div>\n );\n}\n",
"content": "\"use client\";\n\nimport { motion, useInView } from \"framer-motion\";\nimport { Code, Globe, Lock, Shield, Sparkles, Zap } from \"lucide-react\";\nimport { useRef } from \"react\";\n\nconst features = [\n {\n icon: Code,\n title: \"Developer Friendly\",\n description: \"Built with TypeScript and modern React patterns for a superior developer experience.\",\n },\n {\n icon: Zap,\n title: \"Lightning Fast\",\n description: \"Optimized animations and code splitting that ensures your app never lags.\",\n },\n {\n icon: Shield,\n title: \"Production Ready\",\n description: \"Fully tested components that are ready for your next big project launch.\",\n },\n {\n icon: Globe,\n title: \"Responsive\",\n description: \"Layouts that adapt perfectly to any screen size, from mobile to desktop.\",\n },\n {\n icon: Lock,\n title: \"Secure By Default\",\n description: \"Implementation following best security practices to keep your data safe.\",\n },\n {\n icon: Sparkles,\n title: \"Modern Design\",\n description: \"Crafted with the latest web technologies and aesthetic trends in mind.\",\n },\n];\n\nexport function FeatureGridSectionBaseui() {\n const ref = useRef(null);\n const isInView = useInView(ref, { once: true, margin: \"-100px\" });\n\n return (\n <section\n ref={ref}\n className=\"relative w-full overflow-hidden bg-background px-4 py-12 sm:py-16 md:py-20 lg:py-24\"\n >\n {/* Background Pattern */}\n <div className=\"absolute inset-0 -z-10 h-full w-full bg-white dark:bg-black bg-[linear-gradient(to_right,#8080800a_1px,transparent_1px),linear-gradient(to_bottom,#8080800a_1px,transparent_1px)] bg-[size:14px_24px]\"></div>\n\n <div className=\"mx-auto max-w-6xl\">\n <motion.div\n initial={{ opacity: 0, y: 20 }}\n animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}\n transition={{ duration: 0.5 }}\n className=\"mb-12 sm:mb-16 md:mb-20 text-center\"\n >\n <h2 className=\"mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl md:text-5xl\">\n Why Choose Us\n </h2>\n <p className=\"mx-auto max-w-2xl px-4 text-base text-muted-foreground sm:text-lg\">\n Everything you need to build amazing applications, faster and better.\n </p>\n </motion.div>\n\n <div className=\"grid grid-cols-1 gap-6 sm:gap-8 sm:grid-cols-2 lg:grid-cols-3\">\n {features.map((feature, index) => {\n const Icon = feature.icon;\n return (\n <motion.div\n key={feature.title}\n initial={{ opacity: 0, y: 20 }}\n animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}\n transition={{ duration: 0.4, delay: index * 0.1 }}\n className=\"flex\"\n >\n <div className=\"group relative flex h-full w-full flex-col overflow-hidden rounded-xl border border-border/40 bg-background/60 backdrop-blur-sm transition-all duration-300 hover:border-foreground/20 hover:shadow-lg hover:-translate-y-1\">\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100\" />\n\n <div className=\"relative z-10 p-6 pb-4\">\n <div className=\"mb-3 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary group-hover:text-primary-foreground\">\n <Icon className=\"h-6 w-6\" />\n </div>\n <h3 className=\"text-xl font-semibold tracking-tight text-foreground\">\n {feature.title}\n </h3>\n </div>\n <div className=\"relative z-10 p-6 pt-0\">\n <p className=\"text-base text-muted-foreground/90 group-hover:text-muted-foreground transition-colors\">\n {feature.description}\n </p>\n </div>\n </div>\n </motion.div>\n );\n })}\n </div>\n </div>\n </section>\n );\n}\n",
"type": "registry:page",
"target": "components/uitripled/feature-grid-section-baseui.tsx"
}

View file

@ -11,7 +11,7 @@
"files": [
{
"path": "@uitripled/react-shadcn/src/components/sections/feature-grid-section.tsx",
"content": "\"use client\";\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\";\nimport { motion, useInView, type Variants } from \"framer-motion\";\nimport { Code, Globe, Lock, Shield, Sparkles, Zap } from \"lucide-react\";\nimport { useRef } from \"react\";\n\nconst features = [\n {\n icon: Code,\n title: \"Developer Friendly\",\n description: \"Built with TypeScript and modern React patterns\",\n },\n {\n icon: Zap,\n title: \"Lightning Fast\",\n description: \"Optimized animations that never lag\",\n },\n {\n icon: Shield,\n title: \"Production Ready\",\n description: \"Tested and ready for your next project\",\n },\n {\n icon: Globe,\n title: \"Responsive\",\n description: \"Works perfectly on all devices\",\n },\n {\n icon: Lock,\n title: \"Secure\",\n description: \"Built with security best practices\",\n },\n {\n icon: Sparkles,\n title: \"Modern\",\n description: \"Using the latest web technologies\",\n },\n];\n\nexport function FeatureGridSection() {\n const ref = useRef(null);\n const isInView = useInView(ref, { once: true, margin: \"-50px\" });\n\n const containerVariants: Variants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: 0.1,\n delayChildren: 0.2,\n },\n },\n };\n\n const itemVariants: Variants = {\n hidden: { opacity: 0, y: 30, scale: 0.9 },\n visible: {\n opacity: 1,\n y: 0,\n scale: 1,\n transition: {\n type: \"spring\",\n stiffness: 100,\n damping: 15,\n },\n },\n };\n\n return (\n <div ref={ref} className=\"w-full px-4 py-16\">\n <div className=\"mx-auto max-w-6xl\">\n <motion.div\n initial={{ opacity: 0, y: 30 }}\n animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}\n transition={{ duration: 0.6 }}\n className=\"mb-12 text-center\"\n >\n <h2 className=\"mb-4 text-3xl font-bold sm:text-4xl md:text-5xl\">\n Why Choose Us\n </h2>\n <p className=\"text-sm text-[var(--foreground)]/70 sm:text-base md:text-lg\">\n Everything you need to build amazing applications\n </p>\n </motion.div>\n\n <motion.div\n variants={containerVariants}\n initial=\"hidden\"\n animate={isInView ? \"visible\" : \"hidden\"}\n className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\"\n >\n {features.map((feature, index) => {\n const Icon = feature.icon;\n return (\n <motion.div key={feature.title} variants={itemVariants}>\n <Card className=\"h-full bg-[var(--card-bg)] transition-all hover:shadow-lg\">\n <CardHeader>\n <motion.div\n initial={{ opacity: 0, scale: 0.8, rotate: -60 }}\n animate={\n isInView\n ? { opacity: 1, scale: 1, rotate: 0 }\n : { opacity: 0, scale: 0.8, rotate: -60 }\n }\n transition={{\n delay: index * 0.1 + 0.3,\n type: \"spring\",\n stiffness: 120,\n damping: 18,\n mass: 0.6,\n }}\n className=\"mb-4 inline-flex\"\n >\n <Icon\n className=\"h-6 w-6 text-[var(--muted-foreground)]\"\n aria-hidden=\"true\"\n />\n </motion.div>\n <CardTitle className=\"text-xl\">{feature.title}</CardTitle>\n </CardHeader>\n <CardContent>\n <CardDescription className=\"text-base\">\n {feature.description}\n </CardDescription>\n </CardContent>\n </Card>\n </motion.div>\n );\n })}\n </motion.div>\n </div>\n </div>\n );\n}\n",
"content": "\"use client\";\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\";\nimport { motion, useInView } from \"framer-motion\";\nimport { Code, Globe, Lock, Shield, Sparkles, Zap } from \"lucide-react\";\nimport { useRef } from \"react\";\n\nconst features = [\n {\n icon: Code,\n title: \"Developer Friendly\",\n description: \"Built with TypeScript and modern React patterns for a superior developer experience.\",\n },\n {\n icon: Zap,\n title: \"Lightning Fast\",\n description: \"Optimized animations and code splitting that ensures your app never lags.\",\n },\n {\n icon: Shield,\n title: \"Production Ready\",\n description: \"Fully tested components that are ready for your next big project launch.\",\n },\n {\n icon: Globe,\n title: \"Responsive\",\n description: \"Layouts that adapt perfectly to any screen size, from mobile to desktop.\",\n },\n {\n icon: Lock,\n title: \"Secure By Default\",\n description: \"Implementation following best security practices to keep your data safe.\",\n },\n {\n icon: Sparkles,\n title: \"Modern Design\",\n description: \"Crafted with the latest web technologies and aesthetic trends in mind.\",\n },\n];\n\nexport function FeatureGridSection() {\n const ref = useRef(null);\n const isInView = useInView(ref, { once: true, margin: \"-100px\" });\n\n return (\n <section\n ref={ref}\n className=\"relative w-full overflow-hidden bg-background px-4 py-12 sm:py-16 md:py-20 lg:py-24\"\n >\n <div className=\"mx-auto max-w-6xl\">\n <motion.div\n initial={{ opacity: 0, y: 20 }}\n animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}\n transition={{ duration: 0.5 }}\n className=\"mb-12 sm:mb-16 md:mb-20 text-center\"\n >\n <h2 className=\"mb-4 text-3xl font-semibold tracking-tight text-foreground sm:text-4xl md:text-5xl\">\n Why Choose Us\n </h2>\n <p className=\"mx-auto max-w-2xl px-4 text-base text-foreground/70 sm:text-lg\">\n Everything you need to build amazing applications, faster and better.\n </p>\n </motion.div>\n\n <div className=\"grid grid-cols-1 gap-6 sm:gap-8 sm:grid-cols-2 lg:grid-cols-3\">\n {features.map((feature, index) => {\n const Icon = feature.icon;\n return (\n <motion.div\n key={feature.title}\n initial={{ opacity: 0, y: 20 }}\n animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}\n transition={{ duration: 0.4, delay: index * 0.1 }}\n className=\"flex\"\n >\n <Card className=\"group relative flex h-full w-full flex-col overflow-hidden rounded-2xl border border-border/40 bg-background/60 backdrop-blur transition-all duration-300 hover:border-border/60 hover:shadow-lg hover:-translate-y-1\">\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100\" />\n\n <CardHeader className=\"relative pb-4 z-10\">\n <div className=\"mb-4 inline-flex h-12 w-12 items-center justify-center rounded-xl border border-primary/30 bg-primary/20 text-primary transition-colors\">\n <Icon className=\"h-6 w-6\" />\n </div>\n <CardTitle className=\"text-xl font-semibold tracking-tight text-foreground\">\n {feature.title}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"relative z-10\">\n <CardDescription className=\"text-base text-foreground/70 transition-colors\">\n {feature.description}\n </CardDescription>\n </CardContent>\n </Card>\n </motion.div>\n );\n })}\n </div>\n </div>\n </section>\n );\n}\n",
"type": "registry:page",
"target": "components/uitripled/feature-grid-section-shadcnui.tsx"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-avatar-expand",
"type": "registry:component",
"title": "Native Avatar Expand",
"description": "Avatar component that expands to reveal the name on click with smooth animations.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-avatar-expand-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { useState } from \"react\";\n\nexport interface NativeAvatarExpandProps {\n /**\n * URL of the avatar image\n */\n src?: string;\n /**\n * Name of the person or entity\n */\n name: string;\n /**\n * Size variant\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Additional classes for the container\n */\n className?: string;\n /**\n * Additional classes for the avatar\n */\n avatarClassName?: string;\n /**\n * Additional classes for the name text\n */\n nameClassName?: string;\n}\n\nconst sizeConfig = {\n sm: {\n avatar: \"h-10 w-10\",\n text: \"text-sm\",\n },\n md: {\n avatar: \"h-12 w-12\",\n text: \"text-base\",\n },\n lg: {\n avatar: \"h-16 w-16\",\n text: \"text-lg\",\n },\n xl: {\n avatar: \"h-20 w-20\",\n text: \"text-xl\",\n },\n};\n\nexport function NativeAvatarExpand({\n src,\n name,\n size = \"md\",\n className,\n avatarClassName,\n nameClassName,\n}: NativeAvatarExpandProps) {\n const [isExpanded, setIsExpanded] = useState(false);\n const { avatar, text } = sizeConfig[size];\n\n const getInitials = (name: string) => {\n return name\n .split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n };\n\n return (\n <motion.div\n className={cn(\"inline-flex items-center cursor-pointer\", className)}\n layout\n onClick={() => setIsExpanded(!isExpanded)}\n >\n <motion.div layout=\"position\" className=\"relative\">\n <Avatar className={cn(avatar, avatarClassName)}>\n <AvatarImage src={src || \"/placeholder.svg\"} alt={name} />\n <AvatarFallback>{getInitials(name)}</AvatarFallback>\n </Avatar>\n </motion.div>\n\n <AnimatePresence>\n {isExpanded && (\n <motion.div\n initial={{ width: 0, opacity: 0, filter: \"blur(4px)\" }}\n animate={{\n width: \"auto\",\n opacity: 1,\n filter: \"blur(0px)\",\n }}\n exit={{\n width: 0,\n opacity: 0,\n filter: \"blur(4px)\",\n }}\n transition={{\n type: \"spring\",\n stiffness: 200,\n damping: 25,\n opacity: { duration: 0.2 },\n filter: { duration: 0.2 },\n }}\n className=\"overflow-hidden\"\n >\n <motion.span\n initial={{ x: -20 }}\n animate={{ x: 0 }}\n exit={{ x: -20 }}\n transition={{\n type: \"spring\",\n stiffness: 200,\n damping: 25,\n }}\n className={cn(\n \"font-medium whitespace-nowrap ml-1\",\n text,\n nameClassName\n )}\n >\n {name}\n </motion.span>\n </motion.div>\n )}\n </AnimatePresence>\n </motion.div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-avatar-expand.tsx"
}
]
}

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-avatar-with-name",
"type": "registry:component",
"title": "Native Avatar With Name",
"description": "Avatar component that displays a name tooltip on hover with directional animations.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-avatar-with-name-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { useState } from \"react\";\n\nexport interface NativeAvatarProps {\n /**\n * URL of the avatar image\n */\n src?: string;\n /**\n * Name to display on hover\n */\n name: string;\n /**\n * Fallback text when image fails to load (usually initials)\n */\n fallback?: string;\n /**\n * Size variant of the avatar\n * Default: \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Direction from which the name appears\n * Default: \"bottom\"\n */\n direction?: \"top\" | \"bottom\" | \"left\" | \"right\";\n /**\n * Additional class names for the container\n */\n className?: string;\n /**\n * Additional class names for the name label\n */\n nameClassName?: string;\n /**\n * Additional class names for the motion container\n */\n motionClassName?: string;\n}\n\nconst sizeVariants = {\n sm: \"h-10 w-10\",\n md: \"h-14 w-14\",\n lg: \"h-20 w-20\",\n xl: \"h-28 w-28\",\n};\n\nconst nameSizeVariants = {\n sm: \"text-xs px-2 py-1\",\n md: \"text-sm px-3 py-1.5\",\n lg: \"text-base px-4 py-2\",\n xl: \"text-lg px-5 py-2.5\",\n};\n\nexport function NativeAvatarWithName({\n src,\n name,\n fallback,\n size = \"md\",\n direction = \"bottom\",\n className,\n nameClassName,\n motionClassName,\n}: NativeAvatarProps) {\n const [isHovered, setIsHovered] = useState(false);\n\n const getInitials = (name: string) => {\n return name\n .split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n };\n\n const directionVariants = {\n top: {\n initial: { y: 20, opacity: 0, filter: \"blur(4px)\" },\n animate: { y: -8, opacity: 1, filter: \"blur(0px)\" },\n exit: { y: 20, opacity: 0, filter: \"blur(4px)\" },\n },\n bottom: {\n initial: { y: -20, opacity: 0, filter: \"blur(4px)\" },\n animate: { y: 8, opacity: 1, filter: \"blur(0px)\" },\n exit: { y: -20, opacity: 0, filter: \"blur(4px)\" },\n },\n left: {\n initial: { x: 20, opacity: 0, filter: \"blur(4px)\" },\n animate: { x: -8, opacity: 1, filter: \"blur(0px)\" },\n exit: { x: 20, opacity: 0, filter: \"blur(4px)\" },\n },\n right: {\n initial: { x: -20, opacity: 0, filter: \"blur(4px)\" },\n animate: { x: 8, opacity: 1, filter: \"blur(0px)\" },\n exit: { x: -20, opacity: 0, filter: \"blur(4px)\" },\n },\n };\n\n const positionClasses = {\n top: \"bottom-full left-1/2 -translate-x-1/2 mb-2\",\n bottom: \"top-full left-1/2 -translate-x-1/2 mt-2\",\n left: \"right-full top-1/2 -translate-y-1/2 mr-2\",\n right: \"left-full top-1/2 -translate-y-1/2 ml-2\",\n };\n\n return (\n <div\n className={cn(\n \"relative inline-flex items-center justify-center\",\n className\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <motion.div\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 17 }}\n className={motionClassName}\n >\n <Avatar\n className={cn(\n sizeVariants[size],\n \"cursor-pointer ring-2 ring-background shadow-lg\"\n )}\n >\n <AvatarImage src={src || \"/placeholder.svg\"} alt={name} />\n <AvatarFallback className=\"text-muted-foreground font-semibold\">\n {fallback || getInitials(name)}\n </AvatarFallback>\n </Avatar>\n </motion.div>\n\n <AnimatePresence>\n {isHovered && (\n <motion.div\n initial={directionVariants[direction].initial}\n animate={directionVariants[direction].animate}\n exit={directionVariants[direction].exit}\n transition={{\n type: \"spring\",\n stiffness: 300,\n damping: 25,\n opacity: { duration: 0.2 },\n filter: { duration: 0.2 },\n }}\n className={cn(\n \"absolute z-10 whitespace-nowrap rounded-md bg-popover text-popover-foreground shadow-lg border pointer-events-none\",\n nameSizeVariants[size],\n positionClasses[direction],\n nameClassName\n )}\n >\n <span className=\"font-medium\">{name}</span>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-avatar-with-name.tsx"
}
]
}

View file

@ -13,7 +13,7 @@
"path": "@uitripled/react-carbon/src/components/native/native-badge-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { HTMLMotionProps, motion } from \"framer-motion\";\nimport { Sparkles } from \"lucide-react\";\nimport React from \"react\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\",\n {\n variants: {\n variant: {\n default:\n \"border border-primary/20 bg-primary/10 text-primary hover:bg-primary/20 hover:border-primary/40 hover:shadow-[0_0_10px_rgba(var(--primary),0.1)]\",\n neutral:\n \"border border-border/40 bg-card/50 text-muted-foreground backdrop-blur-sm hover:bg-card/80 hover:text-foreground hover:border-border/80\",\n outline:\n \"text-foreground border border-input bg-background/50 backdrop-blur-sm hover:bg-accent hover:text-accent-foreground\",\n glass:\n \"bg-white/10 dark:bg-black/10 backdrop-blur-md border border-white/20 dark:border-white/10 text-foreground shadow-sm hover:bg-white/20 dark:hover:bg-black/20\",\n glow: \"bg-primary/10 text-primary border border-primary/20 shadow-[0_0_10px_rgba(var(--primary),0.2)] hover:shadow-[0_0_20px_rgba(var(--primary),0.4)] hover:bg-primary/20 hover:scale-[1.02]\",\n animated:\n \"group gap-2 tracking-widest uppercase border border-border/60 bg-card/70 text-muted-foreground backdrop-blur hover:border-primary/60 hover:bg-primary/15 hover:text-primary transition-colors duration-300\",\n },\n size: {\n sm: \"text-[10px] px-2 py-0.5\",\n md: \"text-xs px-2.5 py-0.5\",\n lg: \"text-sm px-3.5 py-1\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n }\n);\n\nexport interface NativeBadgeProps\n extends Omit<HTMLMotionProps<\"div\">, \"ref\" | \"children\">,\n VariantProps<typeof badgeVariants> {\n /**\n * Whether to animate the badge on mount.\n * Default: true\n */\n animate?: boolean;\n /**\n * Optional label for the animated variant's secondary tag (e.g., \"new\", \"beta\").\n * Only applies when variant=\"animated\".\n */\n tag?: string;\n /**\n * Optional icon for the animated variant. Defaults to Sparkles.\n * Only applies when variant=\"animated\".\n */\n icon?: React.ReactNode;\n /**\n * Badge content.\n */\n children?: React.ReactNode;\n}\n\nfunction NativeBadge({\n className,\n variant,\n size,\n animate = true,\n tag = \"new\",\n icon,\n children,\n ...props\n}: NativeBadgeProps) {\n const isAnimated = variant === \"animated\";\n const IconElement = icon ?? <Sparkles className=\"h-3 w-3 text-primary\" />;\n\n return (\n <motion.div\n initial={animate ? { opacity: 0, scale: 0.9 } : { opacity: 1, scale: 1 }}\n animate={{ opacity: 1, scale: 1 }}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n transition={{ type: \"spring\", stiffness: 260, damping: 20 }}\n className={cn(badgeVariants({ variant, size }), className)}\n {...props}\n >\n {isAnimated && (\n <motion.span\n animate={{ rotate: [0, 15, -15, 0], opacity: [0.6, 1, 0.6] }}\n transition={{ duration: 2.2, repeat: Infinity, ease: \"easeInOut\" }}\n className=\"inline-block\"\n aria-hidden\n >\n {IconElement}\n </motion.span>\n )}\n {children}\n {isAnimated && tag && (\n <span className=\"rounded-full border border-border/40 bg-white/5 px-2 py-0.5 text-[0.6rem] text-muted-foreground transition-colors duration-300 group-hover:border-primary/60 group-hover:bg-primary/25 group-hover:text-primary\">\n {tag}\n </span>\n )}\n </motion.div>\n );\n}\n\nexport { badgeVariants, NativeBadge };\n",
"type": "registry:component",
"target": "components/uitripled/native-badge.tsx"
"target": "components/uitripled/native-badge-carbon.tsx"
}
]
}

File diff suppressed because one or more lines are too long

View file

@ -11,7 +11,7 @@
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-button-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Button, ButtonProps } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { motion } from \"framer-motion\";\nimport { Loader2 } from \"lucide-react\";\nimport { ReactNode } from \"react\";\n\nexport interface NativeButtonProps extends ButtonProps {\n children: ReactNode;\n loading?: boolean;\n glow?: boolean;\n}\n\nconst NativeButton = ({\n className,\n variant = \"default\",\n size = \"lg\",\n children,\n loading = false,\n glow = false,\n disabled,\n ...props\n}: NativeButtonProps) => {\n const buttonContent = (\n <>\n {loading && <Loader2 className=\"w-4 h-4 mr-2 animate-spin\" />}\n <motion.span\n className={cn(\"flex items-center gap-2\")}\n animate={loading ? { opacity: [1, 0.5, 1] } : { opacity: 1 }}\n transition={\n loading\n ? { duration: 1.5, repeat: Infinity, ease: \"easeInOut\" }\n : { duration: 0.2 }\n }\n >\n {children}\n </motion.span>\n </>\n );\n\n const glassmorphismClassName = cn(\n \"cursor-pointer h-12 rounded-md px-7 text-sm uppercase relative overflow-hidden\",\n !glow && \"shadow-md hover:shadow-lg\",\n glow &&\n \"shadow-lg shadow-primary/20 hover:shadow-primary/40 transition-all duration-300\",\n variant === \"outline\" && \"text-foreground/80 hover:bg-foreground/5\",\n (disabled || loading) && \"opacity-50 cursor-not-allowed grayscale\",\n className\n );\n\n return (\n <motion.div\n whileHover={!disabled && !loading ? { scale: 1.02 } : {}}\n whileTap={!disabled && !loading ? { scale: 0.98 } : {}}\n transition={{ type: \"spring\", stiffness: 400, damping: 17 }}\n className=\"relative block w-fit\"\n >\n {glow && !disabled && !loading && (\n <div className=\"absolute inset-0 rounded-full bg-primary/20 blur-xl opacity-0 hover:opacity-100 transition-opacity duration-500\" />\n )}\n <Button\n variant={variant}\n size={size}\n className={glassmorphismClassName}\n disabled={disabled || loading}\n aria-busy={loading}\n {...props}\n >\n {buttonContent}\n </Button>\n </motion.div>\n );\n};\n\nexport { NativeButton };\n",
"content": "\"use client\";\n\nimport { Button, ButtonProps } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion } from \"framer-motion\";\nimport { Loader2 } from \"lucide-react\";\nimport { ReactNode } from \"react\";\n\nexport interface NativeButtonProps extends ButtonProps {\n children: ReactNode;\n loading?: boolean;\n glow?: boolean;\n}\n\nconst NativeButton = ({\n className,\n variant = \"default\",\n size = \"lg\",\n children,\n loading = false,\n glow = false,\n disabled,\n ...props\n}: NativeButtonProps) => {\n const shouldReduceMotion = useReducedMotion();\n\n const buttonContent = (\n <>\n {loading && <Loader2 className=\"w-4 h-4 mr-2 animate-spin\" />}\n <motion.span\n className={cn(\"flex items-center gap-2\")}\n animate={\n loading\n ? { opacity: shouldReduceMotion ? 1 : [1, 0.5, 1] }\n : { opacity: 1 }\n }\n transition={\n loading && !shouldReduceMotion\n ? { duration: 1, repeat: Infinity, ease: \"easeInOut\" }\n : { duration: 0.2 }\n }\n >\n {children}\n </motion.span>\n </>\n );\n\n const glassmorphismClassName = cn(\n \"cursor-pointer h-12 rounded-md px-7 text-sm relative overflow-hidden\",\n !glow && \"shadow-md hover:shadow-lg\",\n glow &&\n \"shadow-lg shadow-primary/20 hover:shadow-primary/40 transition-[box-shadow,background-color,color,opacity] duration-200\",\n variant === \"outline\" && \"text-foreground/80 hover:bg-foreground/5\",\n (disabled || loading) && \"opacity-50 cursor-not-allowed grayscale\",\n className\n );\n\n return (\n <motion.div\n whileHover={\n !disabled && !loading && !shouldReduceMotion ? { scale: 1.02 } : {}\n }\n whileTap={\n !disabled && !loading && !shouldReduceMotion ? { scale: 0.98 } : {}\n }\n transition={{ type: \"spring\", stiffness: 400, damping: 17 }}\n className=\"relative block w-fit\"\n >\n {glow && !disabled && !loading && (\n <div className=\"absolute inset-0 rounded-full bg-primary/20 blur-xl opacity-0 hover:opacity-100 transition-opacity duration-500\" />\n )}\n <Button\n variant={variant}\n size={size}\n className={glassmorphismClassName}\n disabled={disabled || loading}\n aria-busy={loading}\n {...props}\n >\n {buttonContent}\n </Button>\n </motion.div>\n );\n};\n\nNativeButton.displayName = \"NativeButton\";\n\nexport { NativeButton };\n",
"type": "registry:component",
"target": "components/uitripled/native-button-shadcnui.tsx"
}

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-button",
"type": "registry:component",
"title": "Native Button",
"description": "Glassmorphism-inspired button component based on shadcn/ui with smooth animations and modern styling",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-button-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Button, ButtonProps } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { motion } from \"framer-motion\";\nimport { Loader2 } from \"lucide-react\";\nimport { ReactNode } from \"react\";\n\nexport interface NativeButtonProps extends ButtonProps {\n children: ReactNode;\n loading?: boolean;\n glow?: boolean;\n}\n\nconst NativeButton = ({\n className,\n variant = \"default\",\n size = \"lg\",\n children,\n loading = false,\n glow = false,\n disabled,\n ...props\n}: NativeButtonProps) => {\n const buttonContent = (\n <>\n {loading && <Loader2 className=\"w-4 h-4 mr-2 animate-spin\" />}\n <motion.span\n className={cn(\"flex items-center gap-2\")}\n animate={loading ? { opacity: [1, 0.5, 1] } : { opacity: 1 }}\n transition={\n loading\n ? { duration: 1.5, repeat: Infinity, ease: \"easeInOut\" }\n : { duration: 0.2 }\n }\n >\n {children}\n </motion.span>\n </>\n );\n\n const glassmorphismClassName = cn(\n \"cursor-pointer h-12 rounded-md px-7 text-sm uppercase relative overflow-hidden\",\n !glow && \"shadow-md hover:shadow-lg\",\n glow &&\n \"shadow-lg shadow-primary/20 hover:shadow-primary/40 transition-all duration-300\",\n variant === \"outline\" && \"text-foreground/80 hover:bg-foreground/5\",\n (disabled || loading) && \"opacity-50 cursor-not-allowed grayscale\",\n className\n );\n\n return (\n <motion.div\n whileHover={!disabled && !loading ? { scale: 1.02 } : {}}\n whileTap={!disabled && !loading ? { scale: 0.98 } : {}}\n transition={{ type: \"spring\", stiffness: 400, damping: 17 }}\n className=\"relative block w-fit\"\n >\n {glow && !disabled && !loading && (\n <div className=\"absolute inset-0 rounded-full bg-primary/20 blur-xl opacity-0 hover:opacity-100 transition-opacity duration-500\" />\n )}\n <Button\n variant={variant}\n size={size}\n className={glassmorphismClassName}\n disabled={disabled || loading}\n aria-busy={loading}\n {...props}\n >\n {buttonContent}\n </Button>\n </motion.div>\n );\n};\n\nexport { NativeButton };\n",
"type": "registry:component",
"target": "components/uitripled/native-button.tsx"
}
]
}

View file

@ -13,7 +13,7 @@
"path": "@uitripled/react-carbon/src/components/native/native-counter-up-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { animate, motion, useReducedMotion } from \"framer-motion\";\nimport { useEffect, useState } from \"react\";\n\nexport interface NativeCounterUpProps {\n /**\n * The target number to count up to.\n */\n value: number;\n /**\n * Duration of the animation in seconds.\n * Default: 2\n */\n duration?: number;\n /**\n * Text to display before the number (e.g., \"$\").\n */\n prefix?: string;\n /**\n * Text to display after the number (e.g., \"+\", \"%\").\n */\n suffix?: string;\n /**\n * Number of decimal places to show.\n * Default: 0\n */\n decimals?: number;\n /**\n * Accessible label describing what the counter represents.\n */\n label?: string;\n /**\n * Whether to start the animation on mount.\n * Default: true\n */\n autoStart?: boolean;\n className?: string;\n}\n\nexport function NativeCounterUp({\n value,\n duration = 2,\n prefix = \"\",\n suffix = \"\",\n decimals = 0,\n label,\n autoStart = true,\n className,\n}: NativeCounterUpProps) {\n const shouldReduceMotion = useReducedMotion();\n const [displayValue, setDisplayValue] = useState(0);\n\n useEffect(() => {\n if (!autoStart) return;\n\n // If reduced motion, just set the value immediately\n if (shouldReduceMotion) {\n setDisplayValue(value);\n return;\n }\n\n // Animate from current value to target value\n const controls = animate(0, value, {\n duration,\n ease: [0.16, 1, 0.3, 1], // Smooth expo-out easing\n onUpdate: (latest) => {\n setDisplayValue(\n decimals > 0 ? Number(latest.toFixed(decimals)) : Math.round(latest)\n );\n },\n });\n\n return () => controls.stop();\n }, [value, duration, autoStart, shouldReduceMotion, decimals]);\n\n const formattedValue = displayValue.toLocaleString(undefined, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n });\n\n return (\n <motion.span\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ type: \"spring\", stiffness: 300, damping: 30 }}\n className={cn(\"tabular-nums font-bold\", className)}\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n {prefix}\n {formattedValue}\n {suffix}\n {label && <span className=\"sr-only\">{label}</span>}\n </motion.span>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-counter-up.tsx"
"target": "components/uitripled/native-counter-up-carbon.tsx"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-delete",
"type": "registry:component",
"title": "Native Delete",
"description": "Delete button that expands to show a confirmation button with smooth animations.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-delete-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { Trash2, X } from \"lucide-react\";\nimport { useState } from \"react\";\n\nexport interface NativeDeleteProps {\n /**\n * Callback when delete button is first clicked (shows confirmation)\n */\n onConfirm: () => void;\n /**\n * Callback when delete is confirmed\n */\n onDelete: () => void;\n /**\n * Text to show on the delete button\n * Default: \"Delete\"\n */\n buttonText?: string;\n /**\n * Text to show on the confirm button\n * Default: \"Confirm\"\n */\n confirmText?: string;\n /**\n * Size variant\n * Default: \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /**\n * Show icon in button\n * Default: true\n */\n showIcon?: boolean;\n /**\n * Additional class names for the container\n */\n className?: string;\n /**\n * Disable the button\n */\n disabled?: boolean;\n}\n\nconst sizeVariants = {\n sm: \"h-8 text-xs px-3\",\n md: \"h-10 text-sm px-4\",\n lg: \"h-12 text-base px-6\",\n};\n\nconst iconSizeVariants = {\n sm: \"h-3 w-3\",\n md: \"h-4 w-4\",\n lg: \"h-5 w-5\",\n};\n\nexport function NativeDelete({\n onConfirm,\n onDelete,\n buttonText = \"Delete\",\n confirmText = \"Confirm\",\n size = \"md\",\n showIcon = true,\n className,\n disabled = false,\n}: NativeDeleteProps) {\n const [isExpanded, setIsExpanded] = useState(false);\n\n const handleDeleteClick = () => {\n if (!disabled) {\n setIsExpanded(true);\n onConfirm();\n }\n };\n\n const handleConfirm = () => {\n onDelete();\n setIsExpanded(false);\n };\n\n const handleCancel = () => {\n setIsExpanded(false);\n };\n\n return (\n <div className={cn(\"relative inline-flex items-center gap-2\", className)}>\n <motion.div\n animate={\n isExpanded\n ? {\n filter: [\"blur(0px)\", \"blur(3px)\", \"blur(0px)\"],\n x: [0, -2, 2, -2, 2, 0],\n }\n : {\n filter: \"blur(0px)\",\n x: 0,\n }\n }\n transition={\n isExpanded\n ? {\n filter: { duration: 0.3 },\n x: { duration: 0.4, times: [0, 0.2, 0.4, 0.6, 0.8, 1] },\n }\n : {\n duration: 0.2,\n }\n }\n >\n <motion.div\n whileHover={!disabled ? { scale: 1.02 } : {}}\n whileTap={!disabled ? { scale: 0.98 } : {}}\n transition={{ type: \"spring\", stiffness: 400, damping: 17 }}\n >\n <Button\n variant=\"destructive\"\n size=\"default\"\n className={cn(\n sizeVariants[size],\n \"shadow-md hover:shadow-lg transition-shadow text-white\",\n disabled && \"opacity-50 cursor-not-allowed\"\n )}\n onClick={isExpanded ? handleConfirm : handleDeleteClick}\n disabled={disabled}\n >\n {showIcon && !isExpanded && (\n <Trash2 className={cn(iconSizeVariants[size], \"mr-2\")} />\n )}\n {isExpanded ? confirmText : buttonText}\n </Button>\n </motion.div>\n </motion.div>\n\n <AnimatePresence>\n {isExpanded && (\n <motion.div\n initial={{ opacity: 0, scale: 0.8, x: -10 }}\n animate={{ opacity: 1, scale: 1, x: 0 }}\n exit={{ opacity: 0, scale: 0.8, x: -10 }}\n transition={{\n delay: 0.3,\n type: \"spring\",\n stiffness: 300,\n damping: 25,\n }}\n >\n <motion.div\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 17 }}\n >\n <Button\n variant=\"outline\"\n size=\"icon\"\n className={cn(\n \"shadow-md hover:shadow-lg transition-shadow\",\n size === \"sm\"\n ? \"h-8 w-8\"\n : size === \"md\"\n ? \"h-10 w-10\"\n : \"h-12 w-12\"\n )}\n onClick={handleCancel}\n >\n <X className={iconSizeVariants[size]} />\n </Button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-delete.tsx"
}
]
}

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-dialog",
"type": "registry:component",
"title": "Native Dialog",
"description": "A glassmorphism-styled dialog component with backdrop blur and smooth animations, inspired by native OS modals.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-dialog-shadcnui.tsx",
"content": "\"use client\";\n\nimport {\n DialogDescription as BaseDialogDescription,\n DialogTitle as BaseDialogTitle,\n Dialog,\n DialogClose,\n DialogFooter,\n DialogHeader,\n DialogPortal,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { cn } from \"@/lib/utils\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { motion } from \"framer-motion\";\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\n\nconst NativeDialog = Dialog;\n\nconst NativeDialogTrigger = DialogTrigger;\n\nconst NativeDialogPortal = DialogPortal;\n\nconst NativeDialogClose = DialogClose;\n\nconst NativeDialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay ref={ref} asChild {...props}>\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className={cn(\n \"fixed inset-0 z-50 bg-black/20 backdrop-blur-sm\",\n className\n )}\n />\n </DialogPrimitive.Overlay>\n));\nNativeDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst NativeDialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <NativeDialogPortal>\n <NativeDialogOverlay />\n <DialogPrimitive.Content ref={ref} asChild {...props}>\n <motion.div\n initial={{ opacity: 0, scale: 0.95, filter: \"blur(10px)\" }}\n animate={{ opacity: 1, scale: 1, filter: \"blur(0px)\" }}\n exit={{ opacity: 0, scale: 0.95, filter: \"blur(10px)\" }}\n transition={{ type: \"spring\", duration: 0.5, bounce: 0 }}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-white/10 bg-white/70 dark:bg-neutral-900/70 backdrop-blur-xl p-6 shadow-2xl sm:rounded-2xl\",\n className\n )}\n >\n {children}\n <DialogClose className=\"absolute right-4 top-4 rounded-full p-1 opacity-70 ring-offset-background transition-all hover:opacity-100 hover:bg-black/5 dark:hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogClose>\n </motion.div>\n </DialogPrimitive.Content>\n </NativeDialogPortal>\n));\nNativeDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst NativeDialogHeader = DialogHeader;\nNativeDialogHeader.displayName = \"NativeDialogHeader\";\n\nconst NativeDialogFooter = DialogFooter;\nNativeDialogFooter.displayName = \"NativeDialogFooter\";\n\nconst NativeDialogTitle = BaseDialogTitle;\nNativeDialogTitle.displayName = \"NativeDialogTitle\";\n\nconst NativeDialogDescription = BaseDialogDescription;\nNativeDialogDescription.displayName = \"NativeDialogDescription\";\n\nexport {\n NativeDialog,\n NativeDialogClose,\n NativeDialogContent,\n NativeDialogDescription,\n NativeDialogFooter,\n NativeDialogHeader,\n NativeDialogOverlay,\n NativeDialogPortal,\n NativeDialogTitle,\n NativeDialogTrigger,\n};\n",
"type": "registry:component",
"target": "components/uitripled/native-dialog.tsx"
}
]
}

View file

@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-flip-text-baseui",
"type": "registry:component",
"title": "Native Flip Text",
"description": "Text that flips through words with a 3D blur transition. (Base UI)",
"registryDependencies": [
"button"
],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon-baseui.tsx",
"content": "// Error: Could not read file @uitripled/react-carbon/src/components/native/native-flip-text-carbon-baseui.tsx\n// File not found: @uitripled/react-carbon/src/components/native/native-flip-text-carbon-baseui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-flip-text-baseui.tsx"
}
]
}

View file

@ -0,0 +1,19 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-flip-text-shadcnui",
"type": "registry:component",
"title": "Native Flip Text",
"description": "Text that flips through words with a 3D blur transition.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { useEffect, useState } from \"react\";\n\ninterface NativeFlipTextProps {\n /**\n * Array of words to flip through.\n */\n words: string[];\n /**\n * Duration of each word display in ms.\n * Default: 2000\n */\n duration?: number;\n className?: string;\n}\n\nexport function NativeFlipText({\n words,\n duration = 2000,\n className,\n}: NativeFlipTextProps) {\n const [index, setIndex] = useState(0);\n\n useEffect(() => {\n const interval = setInterval(() => {\n setIndex((prevIndex) => (prevIndex + 1) % words.length);\n }, duration);\n\n return () => clearInterval(interval);\n }, [words.length, duration]);\n\n return (\n <div\n className={cn(\n \"inline-flex items-center justify-center overflow-hidden\",\n className\n )}\n >\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={words[index]}\n initial={{ rotateX: -90, opacity: 0, filter: \"blur(6px)\" }}\n animate={{ rotateX: 0, opacity: 1, filter: \"blur(0px)\" }}\n exit={{ rotateX: 90, opacity: 0, filter: \"blur(6px)\" }}\n transition={{\n type: \"spring\",\n stiffness: 100,\n damping: 20,\n opacity: { duration: 0.3 },\n filter: { duration: 0.3 },\n rotateX: { duration: 0.4 },\n }}\n className=\"text-center\"\n >\n {words[index]}\n </motion.div>\n </AnimatePresence>\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-flip-text-shadcnui.tsx"
}
]
}

View file

@ -13,7 +13,7 @@
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { useEffect, useState } from \"react\";\n\ninterface NativeFlipTextProps {\n /**\n * Array of words to flip through.\n */\n words: string[];\n /**\n * Duration of each word display in ms.\n * Default: 2000\n */\n duration?: number;\n className?: string;\n}\n\nexport function NativeFlipText({\n words,\n duration = 2000,\n className,\n}: NativeFlipTextProps) {\n const [index, setIndex] = useState(0);\n\n useEffect(() => {\n const interval = setInterval(() => {\n setIndex((prevIndex) => (prevIndex + 1) % words.length);\n }, duration);\n\n return () => clearInterval(interval);\n }, [words.length, duration]);\n\n return (\n <div\n className={cn(\n \"inline-flex items-center justify-center overflow-hidden\",\n className\n )}\n >\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={words[index]}\n initial={{ rotateX: -90, opacity: 0, filter: \"blur(6px)\" }}\n animate={{ rotateX: 0, opacity: 1, filter: \"blur(0px)\" }}\n exit={{ rotateX: 90, opacity: 0, filter: \"blur(6px)\" }}\n transition={{\n type: \"spring\",\n stiffness: 100,\n damping: 20,\n opacity: { duration: 0.3 },\n filter: { duration: 0.3 },\n rotateX: { duration: 0.4 },\n }}\n className=\"text-center\"\n >\n {words[index]}\n </motion.div>\n </AnimatePresence>\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-flip-text.tsx"
"target": "components/uitripled/native-flip-text-carbon.tsx"
}
]
}

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-image-checkbox",
"type": "registry:component",
"title": "Native Image Checkbox",
"description": "Image checkbox component with grayscale filter and checkmark indicator.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-image-checkbox-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { cn } from \"@/lib/utils\";\nimport { motion } from \"framer-motion\";\nimport { Check } from \"lucide-react\";\n\nexport interface NativeImageCheckboxProps {\n /**\n * URL of the image\n */\n src: string;\n /**\n * Alt text for the image\n */\n alt: string;\n /**\n * Whether the checkbox is selected\n */\n selected: boolean;\n /**\n * Callback when the checkbox is clicked\n */\n onSelect: (selected: boolean) => void;\n /**\n * Size variant\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Additional classes for the container\n */\n className?: string;\n /**\n * Additional classes for the image\n */\n imageClassName?: string;\n}\n\nconst sizeConfig = {\n sm: {\n container: \"w-20 h-20\",\n check: \"h-5 w-5\",\n checkContainer: \"h-6 w-6\",\n },\n md: {\n container: \"w-28 h-28\",\n check: \"h-6 w-6\",\n checkContainer: \"h-7 w-7\",\n },\n lg: {\n container: \"w-36 h-36\",\n check: \"h-7 w-7\",\n checkContainer: \"h-8 w-8\",\n },\n xl: {\n container: \"w-44 h-44\",\n check: \"h-8 w-8\",\n checkContainer: \"h-9 w-9\",\n },\n};\n\nexport function NativeImageCheckbox({\n src,\n alt,\n selected,\n onSelect,\n size = \"md\",\n className,\n imageClassName,\n}: NativeImageCheckboxProps) {\n const { container, check, checkContainer } = sizeConfig[size];\n\n return (\n <motion.div\n className={cn(\n \"relative cursor-pointer rounded-lg overflow-hidden\",\n container,\n className\n )}\n onClick={() => onSelect(!selected)}\n whileTap={{ scale: 0.95 }}\n transition={{\n type: \"spring\",\n stiffness: 300,\n damping: 20,\n }}\n >\n {/* Image with grayscale filter when not selected */}\n <Avatar className=\"w-full h-full rounded-none\">\n <motion.div\n className=\"w-full h-full\"\n animate={{\n filter: selected ? \"grayscale(0%)\" : \"grayscale(100%)\",\n scale: selected ? 1 : 0.95,\n }}\n transition={{\n type: \"spring\",\n stiffness: 200,\n damping: 25,\n filter: { duration: 0.3 },\n }}\n >\n <AvatarImage\n src={src}\n alt={alt}\n className={cn(\"w-full h-full object-cover\", imageClassName)}\n />\n <AvatarFallback className=\"w-full h-full rounded-none\">\n {alt.slice(0, 2).toUpperCase()}\n </AvatarFallback>\n </motion.div>\n </Avatar>\n\n {/* Overlay for better check visibility */}\n <motion.div\n className=\"absolute inset-0 bg-black\"\n initial={{ opacity: 0 }}\n animate={{ opacity: selected ? 0 : 0.15 }}\n transition={{ duration: 0.3 }}\n />\n\n {/* Check icon with green circle */}\n <motion.div\n className=\"absolute -top-1 -right-1\"\n initial={{ scale: 0, opacity: 0 }}\n animate={{\n scale: selected ? 1 : 0,\n opacity: selected ? 1 : 0,\n }}\n transition={{\n type: \"spring\",\n stiffness: 300,\n damping: 20,\n opacity: { duration: 0.2 },\n }}\n >\n <div\n className={cn(\n \"bg-green-500 rounded-full flex items-center justify-center shadow-lg\",\n checkContainer\n )}\n >\n <Check className={cn(\"text-white stroke-[3]\", check)} />\n </div>\n </motion.div>\n\n {/* Ring border when selected */}\n <motion.div\n className=\"absolute inset-0 rounded-lg border-2 border-green-500\"\n initial={{ opacity: 0 }}\n animate={{ opacity: selected ? 1 : 0 }}\n transition={{ duration: 0.3 }}\n />\n </motion.div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-image-checkbox.tsx"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -13,7 +13,7 @@
"path": "@uitripled/react-carbon/src/components/native/native-magnetic-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n motion,\n Transition,\n useMotionValue,\n useSpring,\n useTransform,\n} from \"framer-motion\";\nimport { useRef, useState } from \"react\";\n\nexport interface NativeMagneticProps {\n /**\n * Content to apply the magnetic effect to.\n */\n children: React.ReactNode;\n /**\n * Strength of the magnetic pull (0-1 range recommended).\n * Default: 0.3\n */\n strength?: number;\n /**\n * Spring stiffness for the animation.\n * Default: 300\n */\n stiffness?: number;\n /**\n * Spring damping for the animation.\n * Default: 30\n */\n damping?: number;\n /**\n * Whether to scale up on hover.\n * Default: true\n */\n scaleOnHover?: boolean;\n /**\n * Wrapper element type.\n * Default: 'div'\n */\n as?: \"div\" | \"button\" | \"a\";\n /**\n * Link href (only applies when as=\"a\").\n */\n href?: string;\n /**\n * Click handler.\n */\n onClick?: () => void;\n className?: string;\n}\n\nconst springTransition: Transition = {\n type: \"spring\",\n stiffness: 400,\n damping: 25,\n};\n\nexport function NativeMagnetic({\n children,\n strength = 0.3,\n stiffness = 300,\n damping = 30,\n scaleOnHover = true,\n as = \"div\",\n href,\n onClick,\n className,\n}: NativeMagneticProps) {\n const ref = useRef<HTMLElement>(null);\n const [, setIsHovered] = useState(false);\n\n const x = useMotionValue(0);\n const y = useMotionValue(0);\n\n const springConfig = { stiffness, damping };\n const springX = useSpring(x, springConfig);\n const springY = useSpring(y, springConfig);\n\n const translateX = useTransform(springX, (v) => v * strength);\n const translateY = useTransform(springY, (v) => v * strength);\n\n const handleMouseMove = (e: React.MouseEvent) => {\n if (!ref.current) return;\n\n const rect = ref.current.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n\n x.set(e.clientX - centerX);\n y.set(e.clientY - centerY);\n };\n\n const handleMouseLeave = () => {\n x.set(0);\n y.set(0);\n setIsHovered(false);\n };\n\n const commonProps = {\n onMouseMove: handleMouseMove,\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: handleMouseLeave,\n style: {\n x: translateX,\n y: translateY,\n },\n whileHover: scaleOnHover ? { scale: 1.05 } : undefined,\n whileTap: { scale: 0.95 },\n transition: springTransition,\n className: cn(\"inline-block cursor-pointer\", className),\n onClick,\n };\n\n if (as === \"a\" && href) {\n return (\n <motion.a\n ref={ref as React.RefObject<HTMLAnchorElement>}\n href={href}\n {...commonProps}\n >\n {children}\n </motion.a>\n );\n }\n\n if (as === \"button\") {\n return (\n <motion.button\n ref={ref as React.RefObject<HTMLButtonElement>}\n type=\"button\"\n {...commonProps}\n >\n {children}\n </motion.button>\n );\n }\n\n return (\n <motion.div ref={ref as React.RefObject<HTMLDivElement>} {...commonProps}>\n {children}\n </motion.div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-magnetic.tsx"
"target": "components/uitripled/native-magnetic-carbon.tsx"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-notification-bell",
"type": "registry:component",
"title": "Native Notification Bell",
"description": "Animated notification bell with badge and ringing effect.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-notification-bell-shadcnui.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion, type Variants } from \"framer-motion\";\nimport { Bell } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nexport interface NativeNotificationBellProps {\n /**\n * Number of notifications to display.\n * Default: 0\n */\n count?: number;\n /**\n * Whether to show the notification badge.\n * Automatically true if count > 0.\n */\n showBadge?: boolean;\n /**\n * Callback when the bell is clicked.\n */\n onClick?: () => void;\n /**\n * Callback when the bell rings (on mount if has notifications).\n */\n onRing?: () => void;\n /**\n * Custom icon to replace the bell.\n */\n icon?: React.ReactNode;\n /**\n * Size variant.\n * Default: 'md'\n */\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n}\n\nconst sizeClasses = {\n sm: \"h-8 w-8\",\n md: \"h-10 w-10\",\n lg: \"h-12 w-12\",\n};\n\nconst iconSizeClasses = {\n sm: \"h-4 w-4\",\n md: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n};\n\nconst badgeSizeClasses = {\n sm: \"h-4 w-4 text-[10px]\",\n md: \"h-5 w-5 text-xs\",\n lg: \"h-6 w-6 text-sm\",\n};\n\nconst ringVariants: Variants = {\n idle: { rotate: 0 },\n ringing: {\n rotate: [0, -15, 15, -10, 10, -5, 5, 0],\n transition: {\n duration: 0.6,\n ease: \"easeInOut\",\n },\n },\n};\n\nexport function NativeNotificationBell({\n count = 0,\n showBadge,\n onClick,\n onRing,\n icon,\n size = \"md\",\n className,\n}: NativeNotificationBellProps) {\n const shouldReduceMotion = useReducedMotion();\n const [isRinging, setIsRinging] = useState(false);\n const hasNotifications = count > 0 || showBadge;\n\n useEffect(() => {\n if (hasNotifications && !shouldReduceMotion) {\n setIsRinging(true);\n const timer = setTimeout(() => setIsRinging(false), 600);\n onRing?.();\n return () => clearTimeout(timer);\n }\n }, [hasNotifications, shouldReduceMotion, onRing]);\n\n const displayCount = count > 99 ? \"99+\" : count > 9 ? \"9+\" : count;\n\n return (\n <div className=\"relative inline-block\">\n <motion.button\n variants={ringVariants}\n animate={isRinging ? \"ringing\" : \"idle\"}\n whileHover={shouldReduceMotion ? undefined : { scale: 1.1 }}\n whileTap={shouldReduceMotion ? undefined : { scale: 0.9 }}\n onClick={onClick}\n className={cn(\n \"relative flex items-center justify-center rounded-full border border-border bg-card transition-colors hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\",\n sizeClasses[size],\n className\n )}\n aria-label={`Notifications${count > 0 ? `, ${count} unread` : \"\"}`}\n >\n {icon ?? <Bell className={iconSizeClasses[size]} />}\n {hasNotifications && (\n <motion.span\n initial={shouldReduceMotion ? { scale: 1 } : { scale: 0 }}\n animate={{ scale: 1 }}\n className={cn(\n \"absolute -right-1 -top-1 flex items-center justify-center rounded-full bg-destructive font-bold text-destructive-foreground\",\n badgeSizeClasses[size]\n )}\n >\n {count > 0 ? displayCount : \"\"}\n </motion.span>\n )}\n </motion.button>\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-notification-bell.tsx"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-tabs",
"type": "registry:component",
"title": "Native Tabs",
"description": "A sleek tabs component with a smooth sliding background indicator using Framer Motion layout animations.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-tabs-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { cn } from \"@/lib/utils\";\nimport { motion } from \"framer-motion\";\nimport { useState } from \"react\";\n\ninterface NativeTabsProps {\n items: {\n id: string;\n label: string;\n content: React.ReactNode;\n }[];\n defaultValue?: string;\n className?: string;\n}\n\nexport function NativeTabs({\n items,\n defaultValue,\n className,\n}: NativeTabsProps) {\n const [activeTab, setActiveTab] = useState(defaultValue || items[0].id);\n\n return (\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n className={cn(\"w-full max-w-md\", className)}\n >\n <TabsList className=\"relative flex w-full items-center gap-1 rounded-xl bg-muted/50 p-1 border border-black/5 dark:border-white/5\">\n {items.map((tab) => {\n const isActive = activeTab === tab.id;\n return (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n className=\"relative z-10 flex-1 rounded-lg px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 data-[state=active]:text-foreground data-[state=inactive]:text-muted-foreground data-[state=inactive]:hover:text-foreground data-[state=active]:bg-transparent data-[state=active]:shadow-none\"\n >\n {isActive && (\n <motion.div\n layoutId=\"active-tab\"\n className=\"absolute inset-0 z-[-1] rounded-lg bg-background shadow-sm border border-black/5 dark:border-white/5\"\n transition={{ type: \"spring\", bounce: 0.2, duration: 0.6 }}\n />\n )}\n {tab.label}\n </TabsTrigger>\n );\n })}\n </TabsList>\n {items.map((item) => (\n <TabsContent\n key={item.id}\n value={item.id}\n className=\"mt-4 overflow-hidden rounded-xl border bg-background p-6 shadow-sm\"\n >\n <motion.div\n initial={{ opacity: 0, x: -10 }}\n animate={{ opacity: 1, x: 0 }}\n exit={{ opacity: 0, x: 10 }}\n transition={{ duration: 0.2 }}\n >\n {item.content}\n </motion.div>\n </TabsContent>\n ))}\n </Tabs>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-tabs.tsx"
}
]
}

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-tooltip",
"type": "registry:component",
"title": "Native Tooltip",
"description": "A glassmorphism-styled tooltip with smooth spring animations using Framer Motion.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-tooltip-shadcnui.tsx",
"content": "\"use client\";\n\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport { motion } from \"framer-motion\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst NativeTooltipProvider = ({\n delayDuration = 100,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) => (\n <TooltipPrimitive.Provider delayDuration={delayDuration} {...props} />\n);\n\nconst NativeTooltipRoot = TooltipPrimitive.Root;\n\nconst NativeTooltipTrigger = TooltipPrimitive.Trigger;\n\nconst NativeTooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & {\n animation?: \"blur\" | \"scale\";\n }\n>(\n (\n { className, sideOffset = 8, children, animation = \"blur\", ...props },\n ref\n ) => {\n const animations = {\n blur: {\n initial: { opacity: 0, scale: 0.9, filter: \"blur(4px)\" },\n animate: { opacity: 1, scale: 1, filter: \"blur(0px)\" },\n transition: { type: \"spring\", duration: 0.4, bounce: 0 } as any,\n },\n scale: {\n initial: { opacity: 0, scale: 0.5, y: 10 },\n animate: { opacity: 1, scale: 1, y: 0 },\n transition: { type: \"spring\", duration: 0.4, bounce: 0.4 } as any,\n },\n };\n\n const selectedAnimation = animations[animation];\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"z-50 overflow-visible bg-transparent\", className)}\n {...props}\n >\n <motion.div\n initial={selectedAnimation.initial}\n animate={selectedAnimation.animate}\n transition={selectedAnimation.transition}\n className=\"rounded-md border border-white/10 bg-black/80 dark:bg-white/90 backdrop-blur-md px-3 py-1.5 text-xs font-medium text-white dark:text-black shadow-lg\"\n >\n {children}\n </motion.div>\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n }\n);\nNativeTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nconst NativeTooltip = ({\n content,\n children,\n animation,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root> & {\n content?: React.ReactNode;\n animation?: \"blur\" | \"scale\";\n}) => {\n if (content) {\n return (\n <NativeTooltipRoot {...props}>\n <NativeTooltipTrigger asChild>{children}</NativeTooltipTrigger>\n <NativeTooltipContent animation={animation}>\n {content}\n </NativeTooltipContent>\n </NativeTooltipRoot>\n );\n }\n\n return <NativeTooltipRoot {...props}>{children}</NativeTooltipRoot>;\n};\n\nexport {\n NativeTooltip,\n NativeTooltipContent,\n NativeTooltipProvider,\n NativeTooltipTrigger,\n};\n",
"type": "registry:component",
"target": "components/uitripled/native-tooltip.tsx"
}
]
}

View file

@ -0,0 +1,19 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-typewriter-shadcnui",
"type": "registry:component",
"title": "Native Typewriter",
"description": "Typewriter effect with speed control, looping, and blinking cursor.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/native-typewriter-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion } from \"framer-motion\";\nimport { useEffect, useState } from \"react\";\n\ninterface NativeTypewriterProps {\n /**\n * The text content to type. Can be a string or an array of strings.\n * If an array, it will type each string in sequence (or loop if loop=true).\n */\n content: string | string[];\n /**\n * Typing speed.\n * 'slow' = 100ms, 'medium' = 50ms, 'fast' = 30ms.\n * Or pass a number in ms.\n * Default: 'medium'\n */\n speed?: \"slow\" | \"medium\" | \"fast\" | number;\n /**\n * Whether to show a blinking cursor.\n * Default: true\n */\n cursor?: boolean;\n /**\n * Whether to loop the typing animation.\n * Default: false\n */\n loop?: boolean;\n /**\n * Delay before starting animation in ms.\n * Default: 0\n */\n startDelay?: number;\n /**\n * Whether to apply a blur/morph effect to each character.\n * Default: true\n */\n morph?: boolean;\n className?: string;\n}\n\nexport function NativeTypewriter({\n content,\n speed = \"medium\",\n cursor = true,\n loop = false,\n startDelay = 0,\n morph = true,\n className,\n}: NativeTypewriterProps) {\n const shouldReduceMotion = useReducedMotion();\n const [displayedText, setDisplayedText] = useState(\"\");\n const [isStarted, setIsStarted] = useState(false);\n\n // Calculate delay calculation\n const speedMap = {\n slow: 100,\n medium: 50,\n fast: 30,\n };\n const typingSpeed = typeof speed === \"number\" ? speed : speedMap[speed];\n\n useEffect(() => {\n // If reduced motion is enabled, just show the full text immediately\n if (shouldReduceMotion) {\n setDisplayedText(Array.isArray(content) ? content.join(\" \") : content);\n return;\n }\n\n let timeoutId: NodeJS.Timeout;\n let currentIndex = 0;\n let currentStringIndex = 0;\n\n // Normalize content to array\n const textArray = Array.isArray(content) ? content : [content];\n\n // Actually, simpler logic for a first pass is often better.\n // Let's implement a robust \"Type -> Wait -> (Delete if multi/loop) -> Next\" cycle.\n\n let isDeleting = false;\n\n // Unified typing loop logic\n const runLoop = () => {\n const currentString = textArray[currentStringIndex];\n\n if (isDeleting) {\n setDisplayedText(currentString.substring(0, currentIndex));\n currentIndex--;\n if (currentIndex < 0) {\n isDeleting = false;\n currentIndex = 0;\n currentStringIndex = (currentStringIndex + 1) % textArray.length;\n if (!loop && currentStringIndex === 0) {\n return;\n }\n timeoutId = setTimeout(runLoop, 500);\n } else {\n timeoutId = setTimeout(runLoop, typingSpeed / 2);\n }\n } else {\n setDisplayedText(currentString.substring(0, currentIndex + 1));\n currentIndex++;\n if (currentIndex > currentString.length) {\n if (\n (textArray.length > 1 &&\n (loop || currentStringIndex < textArray.length - 1)) ||\n (textArray.length === 1 && loop)\n ) {\n isDeleting = true;\n currentIndex = currentString.length;\n timeoutId = setTimeout(runLoop, 2000);\n }\n } else {\n timeoutId = setTimeout(runLoop, typingSpeed);\n }\n }\n };\n\n const initialTimer = setTimeout(() => {\n setIsStarted(true);\n runLoop();\n }, startDelay);\n\n return () => {\n clearTimeout(initialTimer);\n clearTimeout(timeoutId);\n };\n }, [content, typingSpeed, loop, startDelay, shouldReduceMotion]);\n\n return (\n <div className={cn(\"inline-flex items-center\", className)}>\n <span className=\"whitespace-pre-wrap\">\n {displayedText.split(\"\").map((char, index) => (\n <motion.span\n key={index}\n initial={\n morph ? { opacity: 0, filter: \"blur(2px)\" } : { opacity: 1 }\n }\n animate={\n morph ? { opacity: 1, filter: \"blur(0px)\" } : { opacity: 1 }\n }\n transition={{ duration: 0.1 }}\n >\n {char}\n </motion.span>\n ))}\n </span>\n {cursor && (\n <motion.span\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{\n duration: 0.5,\n repeat: Infinity,\n repeatType: \"reverse\",\n ease: \"linear\",\n }}\n className=\"ml-0.5 inline-block h-[1.2em] w-[2px] bg-primary align-bottom\"\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-typewriter-shadcnui.tsx"
}
]
}

View file

@ -13,7 +13,7 @@
"path": "@uitripled/react-carbon/src/components/native/native-typewriter-carbon.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion } from \"framer-motion\";\nimport { useEffect, useState } from \"react\";\n\ninterface NativeTypewriterProps {\n /**\n * The text content to type. Can be a string or an array of strings.\n * If an array, it will type each string in sequence (or loop if loop=true).\n */\n content: string | string[];\n /**\n * Typing speed.\n * 'slow' = 100ms, 'medium' = 50ms, 'fast' = 30ms.\n * Or pass a number in ms.\n * Default: 'medium'\n */\n speed?: \"slow\" | \"medium\" | \"fast\" | number;\n /**\n * Whether to show a blinking cursor.\n * Default: true\n */\n cursor?: boolean;\n /**\n * Whether to loop the typing animation.\n * Default: false\n */\n loop?: boolean;\n /**\n * Delay before starting animation in ms.\n * Default: 0\n */\n startDelay?: number;\n /**\n * Whether to apply a blur/morph effect to each character.\n * Default: true\n */\n morph?: boolean;\n className?: string;\n}\n\nexport function NativeTypewriter({\n content,\n speed = \"medium\",\n cursor = true,\n loop = false,\n startDelay = 0,\n morph = true,\n className,\n}: NativeTypewriterProps) {\n const shouldReduceMotion = useReducedMotion();\n const [displayedText, setDisplayedText] = useState(\"\");\n const [isStarted, setIsStarted] = useState(false);\n\n // Calculate delay calculation\n const speedMap = {\n slow: 100,\n medium: 50,\n fast: 30,\n };\n const typingSpeed = typeof speed === \"number\" ? speed : speedMap[speed];\n\n useEffect(() => {\n // If reduced motion is enabled, just show the full text immediately\n if (shouldReduceMotion) {\n setDisplayedText(Array.isArray(content) ? content.join(\" \") : content);\n return;\n }\n\n let timeoutId: NodeJS.Timeout;\n let currentIndex = 0;\n let currentStringIndex = 0;\n\n // Normalize content to array\n const textArray = Array.isArray(content) ? content : [content];\n\n // Actually, simpler logic for a first pass is often better.\n // Let's implement a robust \"Type -> Wait -> (Delete if multi/loop) -> Next\" cycle.\n\n let isDeleting = false;\n\n // Unified typing loop logic\n const runLoop = () => {\n const currentString = textArray[currentStringIndex];\n\n if (isDeleting) {\n setDisplayedText(currentString.substring(0, currentIndex));\n currentIndex--;\n if (currentIndex < 0) {\n isDeleting = false;\n currentIndex = 0;\n currentStringIndex = (currentStringIndex + 1) % textArray.length;\n if (!loop && currentStringIndex === 0) {\n return;\n }\n timeoutId = setTimeout(runLoop, 500);\n } else {\n timeoutId = setTimeout(runLoop, typingSpeed / 2);\n }\n } else {\n setDisplayedText(currentString.substring(0, currentIndex + 1));\n currentIndex++;\n if (currentIndex > currentString.length) {\n if (\n (textArray.length > 1 &&\n (loop || currentStringIndex < textArray.length - 1)) ||\n (textArray.length === 1 && loop)\n ) {\n isDeleting = true;\n currentIndex = currentString.length;\n timeoutId = setTimeout(runLoop, 2000);\n }\n } else {\n timeoutId = setTimeout(runLoop, typingSpeed);\n }\n }\n };\n\n const initialTimer = setTimeout(() => {\n setIsStarted(true);\n runLoop();\n }, startDelay);\n\n return () => {\n clearTimeout(initialTimer);\n clearTimeout(timeoutId);\n };\n }, [content, typingSpeed, loop, startDelay, shouldReduceMotion]);\n\n return (\n <div className={cn(\"inline-flex items-center\", className)}>\n <span className=\"whitespace-pre-wrap\">\n {displayedText.split(\"\").map((char, index) => (\n <motion.span\n key={index}\n initial={\n morph ? { opacity: 0, filter: \"blur(2px)\" } : { opacity: 1 }\n }\n animate={\n morph ? { opacity: 1, filter: \"blur(0px)\" } : { opacity: 1 }\n }\n transition={{ duration: 0.1 }}\n >\n {char}\n </motion.span>\n ))}\n </span>\n {cursor && (\n <motion.span\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{\n duration: 0.5,\n repeat: Infinity,\n repeatType: \"reverse\",\n ease: \"linear\",\n }}\n className=\"ml-0.5 inline-block h-[1.2em] w-[2px] bg-primary align-bottom\"\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-typewriter.tsx"
"target": "components/uitripled/native-typewriter-carbon.tsx"
}
]
}

View file

@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-user-card-baseui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)",
"registryDependencies": [
"button"
],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/native/native-user-card-baseui.tsx",
"content": "\"use client\";\n\nimport { Avatar } from \"@base-ui/react/avatar\";\nimport { Button } from \"@base-ui/react/button\";\nimport { cn } from \"@/lib/utils\";\nimport { motion, MotionConfig } from \"framer-motion\";\nimport { ArrowRight } from \"lucide-react\";\n\ninterface NativeUserCardProps {\n imageSrc: string;\n name: string;\n handle: string;\n href?: string;\n onClick?: () => void;\n className?: string;\n}\n\nconst transition = {\n type: \"spring\" as const,\n stiffness: 400,\n damping: 30,\n};\n\nexport function NativeUserCard({\n imageSrc,\n name,\n handle,\n href = \"#\",\n onClick,\n className,\n}: NativeUserCardProps) {\n const CardContent = (\n <motion.div\n initial={{ opacity: 0, scale: 0.98, y: 5 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n transition={transition}\n className={cn(\n \"group relative flex w-full max-w-full items-center justify-between gap-4 rounded-lg border border-border bg-card p-1 transition-all duration-300\",\n className\n )}\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <div className=\"relative h-10 w-10 shrink-0 overflow-hidden rounded-lg sm:h-12 sm:w-12\">\n <Avatar.Root className=\"h-full w-full rounded-lg\">\n <Avatar.Image src={imageSrc} alt={name} className=\"h-full w-full object-cover\" />\n <Avatar.Fallback className=\"flex h-full w-full items-center justify-center bg-muted text-muted-foreground font-semibold\">\n {name.charAt(0)}\n </Avatar.Fallback>\n </Avatar.Root>\n </div>\n\n <div className=\"flex min-w-0 flex-col\">\n <h3 className=\"truncate text-sm font-semibold leading-none tracking-tight text-foreground\">\n {name}\n </h3>\n <p className=\"truncate text-xs font-medium text-muted-foreground\">\n {handle}\n </p>\n </div>\n </div>\n\n <div className=\"relative shrink-0 pl-2\">\n <Button\n className={cn(\n \"flex h-10 w-10 shrink-0 cursor-pointer items-center justify-center rounded-lg bg-primary text-primary-foreground opacity-100 transition-transform duration-300 group-hover:scale-105 sm:h-12 sm:w-12\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n )}\n >\n <motion.div whileTap={{ scale: 0.95 }}>\n <ArrowRight className=\"h-3 w-3\" />\n </motion.div>\n </Button>\n </div>\n </motion.div>\n );\n\n return (\n <MotionConfig transition={transition}>\n {onClick ? (\n <Button\n onClick={onClick}\n className=\"block w-full max-w-full text-left outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-lg h-auto p-0 hover:bg-transparent\"\n aria-label={`View profile of ${name}`}\n >\n {CardContent}\n </Button>\n ) : (\n <a\n href={href}\n className=\"block w-full max-w-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-lg\"\n aria-label={`View profile of ${name}`}\n >\n {CardContent}\n </a>\n )}\n </MotionConfig>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-user-card-baseui.tsx"
}
]
}

View file

@ -0,0 +1,19 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "native-user-card-shadcnui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-user-card-shadcnui.tsx",
"content": "\"use client\";\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { motion } from \"framer-motion\";\nimport { ArrowRight } from \"lucide-react\";\nimport Link from \"next/link\";\n\ninterface NativeUserCardProps {\n imageSrc: string;\n name: string;\n handle: string;\n href?: string;\n onClick?: () => void;\n className?: string;\n}\n\nexport function NativeUserCard({\n imageSrc,\n name,\n handle,\n href = \"#\",\n onClick,\n className,\n}: NativeUserCardProps) {\n const CardContent = (\n <motion.div\n initial={{ opacity: 0, scale: 0.98, y: 5 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n transition={{\n type: \"spring\",\n stiffness: 400,\n damping: 30,\n }}\n className={cn(\n \"group relative flex w-full max-w-full items-center justify-between gap-4 rounded-lg border border-border bg-card p-1 transition-all duration-300\",\n className\n )}\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <div className=\"relative h-10 w-10 shrink-0 overflow-hidden rounded-lg sm:h-12 sm:w-12\">\n <Avatar className=\"h-full w-full rounded-lg\">\n <AvatarImage src={imageSrc} alt={name} className=\"object-cover\" />\n <AvatarFallback>{name.charAt(0)}</AvatarFallback>\n </Avatar>\n </div>\n\n <div className=\"flex min-w-0 flex-col\">\n <h3 className=\"truncate text-sm font-semibold leading-none tracking-tight text-foreground\">\n {name}\n </h3>\n <p className=\"truncate text-xs font-medium text-muted-foreground\">\n {handle}\n </p>\n </div>\n </div>\n\n <div className=\"relative shrink-0 pl-2\">\n <Button\n size=\"icon\"\n className=\"h-10 w-10 shrink-0 rounded-lg bg-primary text-primary-foreground opacity-100 transition-transform duration-300 group-hover:scale-105 sm:h-12 sm:w-12\"\n asChild\n >\n <motion.div\n whileTap={{ scale: 0.95 }}\n >\n <ArrowRight className=\"h-3 w-3\" />\n </motion.div>\n </Button>\n </div>\n </motion.div>\n );\n\n if (onClick) {\n return (\n <Button onClick={onClick} className=\"block w-full max-w-full text-left outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-lg h-auto p-0 hover:bg-transparent\">\n {CardContent}\n </Button>\n );\n }\n\n return (\n <Link href={href} className={cn(\"block w-full max-w-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-lg\")}>\n {CardContent}\n </Link>\n );\n}\n",
"type": "registry:component",
"target": "components/uitripled/native-user-card-shadcnui.tsx"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1301,6 +1301,28 @@
"category": "components",
"subcategory": null
},
{
"name": "dashboard-baseui",
"type": "registry:block",
"title": "Dashboard",
"description": "Interactive stock portfolio dashboard with status cards, data table, and detailed stock information modal (Base UI)",
"registryDependencies": [
"button"
],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/stocks-dashboard/dashboard-baseui.tsx",
"type": "registry:block",
"target": "components/uitripled/dashboard-baseui.tsx"
}
],
"category": "sections",
"subcategory": null
},
{
"name": "dashboard-shadcnui",
"type": "registry:block",
@ -1878,6 +1900,46 @@
"category": "components",
"subcategory": "modal"
},
{
"name": "folder-animation",
"type": "registry:ui",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:ui",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "decorative",
"subcategory": null
},
{
"name": "folder-animation-carbon",
"type": "registry:component",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "footer-block-baseui",
"type": "registry:block",
@ -3306,26 +3368,6 @@
"category": "sections",
"subcategory": null
},
{
"name": "native-avatar-expand",
"type": "registry:component",
"title": "Native Avatar Expand",
"description": "Avatar component that expands to reveal the name on click with smooth animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-avatar-expand-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-avatar-expand.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-avatar-expand-baseui",
"type": "registry:component",
@ -3368,26 +3410,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-avatar-with-name",
"type": "registry:component",
"title": "Native Avatar With Name",
"description": "Avatar component that displays a name tooltip on hover with directional animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-avatar-with-name-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-avatar-with-name.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-avatar-with-name-baseui",
"type": "registry:component",
@ -3444,7 +3466,7 @@
{
"path": "@uitripled/react-carbon/src/components/native/native-badge-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-badge.tsx"
"target": "components/uitripled/native-badge-carbon.tsx"
}
],
"category": "native",
@ -3470,26 +3492,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-button",
"type": "registry:component",
"title": "Native Button",
"description": "Glassmorphism-inspired button component based on shadcn/ui with smooth animations and modern styling",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-button-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-button.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-button-baseui",
"type": "registry:component",
@ -3546,7 +3548,7 @@
{
"path": "@uitripled/react-carbon/src/components/native/native-counter-up-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-counter-up.tsx"
"target": "components/uitripled/native-counter-up-carbon.tsx"
}
],
"category": "native",
@ -3572,26 +3574,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-delete",
"type": "registry:component",
"title": "Native Delete",
"description": "Delete button that expands to show a confirmation button with smooth animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-delete-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-delete.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-delete-baseui",
"type": "registry:component",
@ -3634,26 +3616,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-dialog",
"type": "registry:component",
"title": "Native Dialog",
"description": "A glassmorphism-styled dialog component with backdrop blur and smooth animations, inspired by native OS modals.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-dialog-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-dialog.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-dialog-baseui",
"type": "registry:component",
@ -3710,7 +3672,29 @@
{
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-flip-text.tsx"
"target": "components/uitripled/native-flip-text-carbon.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-flip-text-baseui",
"type": "registry:component",
"title": "Native Flip Text",
"description": "Text that flips through words with a 3D blur transition. (Base UI)",
"registryDependencies": [
"button"
],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon-baseui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-flip-text-baseui.tsx"
}
],
"category": "native",
@ -3736,6 +3720,26 @@
"category": "native",
"subcategory": null
},
{
"name": "native-flip-text-shadcnui",
"type": "registry:component",
"title": "Native Flip Text",
"description": "Text that flips through words with a 3D blur transition.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/native-flip-text-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-flip-text-shadcnui.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-follow-cursor",
"type": "registry:component",
@ -3776,26 +3780,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-hover-card",
"type": "registry:component",
"title": "Native Hover Card",
"description": "Avatar card that expands on hover to reveal profile information with smooth animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-hover-card-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-hover-card.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-hover-card-baseui",
"type": "registry:component",
@ -3838,26 +3822,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-image-checkbox",
"type": "registry:component",
"title": "Native Image Checkbox",
"description": "Image checkbox component with grayscale filter and checkmark indicator.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-image-checkbox-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-image-checkbox.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-image-checkbox-baseui",
"type": "registry:component",
@ -3920,26 +3884,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-likes-counter",
"type": "registry:component",
"title": "Native Likes Counter",
"description": "An interactive likes counter with avatar stack, popup details, and smooth animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-likes-counter-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-likes-counter.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-likes-counter-baseui",
"type": "registry:component",
@ -3982,26 +3926,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-liquid-button",
"type": "registry:component",
"title": "Native Liquid Button",
"description": "Button with animated liquid fill effect, progress tracking, and multiple visual variants for engaging interactions.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-liquid-button-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-liquid-button.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-liquid-button-baseui",
"type": "registry:component",
@ -4058,7 +3982,7 @@
{
"path": "@uitripled/react-carbon/src/components/native/native-magnetic-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-magnetic.tsx"
"target": "components/uitripled/native-magnetic-carbon.tsx"
}
],
"category": "native",
@ -4126,26 +4050,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-morphing-button",
"type": "registry:component",
"title": "Native Morphing Button",
"description": "Floating action button that morphs into a menu of actions.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-morphing-button-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-morphing-button.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-morphing-button-baseui",
"type": "registry:component",
@ -4208,26 +4112,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-nested-list",
"type": "registry:component",
"title": "Native Nested List",
"description": "A nested list component with smooth expand/collapse animations, perfect for file explorers or navigation menus.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-nested-list-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-nested-list.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-nested-list-baseui",
"type": "registry:component",
@ -4251,10 +4135,10 @@
"subcategory": null
},
{
"name": "native-notification-bell",
"name": "native-nested-list-shadcnui",
"type": "registry:component",
"title": "Native Notification Bell",
"description": "Animated notification bell with badge and ringing effect.",
"title": "Native Nested List",
"description": "A nested list component with smooth expand/collapse animations, perfect for file explorers or navigation menus.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
@ -4262,9 +4146,51 @@
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-notification-bell-shadcnui.tsx",
"path": "@uitripled/react-shadcn/src/components/native/native-nested-list-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-notification-bell.tsx"
"target": "components/uitripled/native-nested-list-shadcnui.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-notch-baseui",
"type": "registry:component",
"title": "Native Notch",
"description": "Dynamic Island-inspired notch component with smooth spring animations, draggable physics, and expandable content area (Base UI)",
"registryDependencies": [
"button"
],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/native/native-notch-baseui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-notch-baseui.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-notch-shadcnui",
"type": "registry:component",
"title": "Native Notch",
"description": "Dynamic Island-inspired notch component with smooth spring animations, draggable physics, and expandable content area",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-notch-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-notch-shadcnui.tsx"
}
],
"category": "native",
@ -4332,26 +4258,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-profile-notch",
"type": "registry:component",
"title": "Native Profile Notch",
"description": "A dynamic expanding notch component for displaying user profiles with smooth spring animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-profile-notch-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-profile-notch.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-profile-notch-baseui",
"type": "registry:component",
@ -4394,26 +4300,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-start-now",
"type": "registry:component",
"title": "Native Start Now",
"description": "Animated button with sparkle effects, loading states, and smooth transitions for starting actions.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-start-now-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-start-now.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-start-now-baseui",
"type": "registry:component",
@ -4456,26 +4342,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-tabs",
"type": "registry:component",
"title": "Native Tabs",
"description": "A sleek tabs component with a smooth sliding background indicator using Framer Motion layout animations.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-tabs-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-tabs.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-tabs-baseui",
"type": "registry:component",
@ -4538,26 +4404,6 @@
"category": "native",
"subcategory": null
},
{
"name": "native-tooltip",
"type": "registry:component",
"title": "Native Tooltip",
"description": "A glassmorphism-styled tooltip with smooth spring animations using Framer Motion.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-tooltip-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-tooltip.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-tooltip-baseui",
"type": "registry:component",
@ -4614,7 +4460,7 @@
{
"path": "@uitripled/react-carbon/src/components/native/native-typewriter-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-typewriter.tsx"
"target": "components/uitripled/native-typewriter-carbon.tsx"
}
],
"category": "native",
@ -4643,10 +4489,10 @@
"subcategory": null
},
{
"name": "native-verified-badge",
"name": "native-typewriter-shadcnui",
"type": "registry:component",
"title": "Native Verified Badge",
"description": "Verified badge component with multiple variants, sizes, and styles including outline and shield designs.",
"title": "Native Typewriter",
"description": "Typewriter effect with speed control, looping, and blinking cursor.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
@ -4654,14 +4500,56 @@
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-verified-badge-shadcnui.tsx",
"path": "@uitripled/react-carbon/src/components/native/native-typewriter-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/native-verified-badge.tsx"
"target": "components/uitripled/native-typewriter-shadcnui.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "native-user-card-baseui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)",
"registryDependencies": [
"button"
],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/native/native-user-card-baseui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-user-card-baseui.tsx"
}
],
"category": "cards",
"subcategory": null
},
{
"name": "native-user-card-shadcnui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/native-user-card-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/native-user-card-shadcnui.tsx"
}
],
"category": "cards",
"subcategory": null
},
{
"name": "native-verified-badge-baseui",
"type": "registry:component",
@ -5429,26 +5317,6 @@
"category": "components",
"subcategory": null
},
{
"name": "social-login-button",
"type": "registry:component",
"title": "Social Login Button",
"description": "A set of animated social login buttons for major platforms (Github, Google, X, etc.) with various effects.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/social-login-button-shadcnui.tsx",
"type": "registry:component",
"target": "components/uitripled/social-login-button.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "social-login-button-baseui",
"type": "registry:component",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "social-login-button",
"type": "registry:component",
"title": "Social Login Button",
"description": "A set of animated social login buttons for major platforms (Github, Google, X, etc.) with various effects.",
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-shadcn/src/components/native/social-login-button-shadcnui.tsx",
"content": "import { Button, ButtonProps } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { motion } from \"framer-motion\";\nimport { Chrome, Github, Linkedin, Triangle, Twitter } from \"lucide-react\";\nimport { ReactNode } from \"react\";\n\nexport type SocialProvider = \"github\" | \"google\" | \"x\" | \"vercel\" | \"linkedin\";\nexport type SocialAnimation = \"slide\" | \"scale\" | \"glow\" | \"shine\" | \"none\";\n\nexport interface SocialLoginButtonProps extends ButtonProps {\n provider: SocialProvider;\n animation?: SocialAnimation;\n children?: ReactNode; // Optional, defaults to \"Continue with [Provider]\"\n}\n\nconst providerConfig: Record<\n SocialProvider,\n {\n icon: React.ComponentType<{ className?: string }>;\n label: string;\n bgClass: string;\n textClass?: string;\n }\n> = {\n github: {\n icon: Github,\n label: \"Verify with Github\",\n bgClass:\n \"bg-black text-white hover:bg-black/90 dark:bg-white dark:text-black dark:hover:bg-white/90\",\n },\n google: {\n icon: Chrome,\n label: \"Continue with Google\",\n bgClass:\n \"bg-white text-black border border-input hover:bg-accent hover:text-accent-foreground dark:bg-neutral-900 dark:text-white dark:border-neutral-800\",\n },\n x: {\n icon: Twitter,\n label: \"Sign in with X\",\n bgClass:\n \"bg-black text-white hover:bg-black/90 dark:bg-white dark:text-black dark:hover:bg-white/90\",\n },\n vercel: {\n icon: Triangle,\n label: \"Continue with Vercel\",\n bgClass:\n \"bg-black text-white hover:bg-black/90 dark:bg-white dark:text-black dark:hover:bg-white/90\",\n },\n linkedin: {\n icon: Linkedin,\n label: \"Connect with LinkedIn\",\n bgClass:\n \"bg-black text-white hover:bg-black/90 dark:bg-white dark:text-black dark:hover:bg-white/90\",\n },\n};\n\nconst SocialLoginButton = ({\n className,\n provider,\n animation = \"none\",\n children,\n ...props\n}: SocialLoginButtonProps) => {\n const config = providerConfig[provider];\n const Icon = config.icon;\n\n const baseStyles = cn(\n \"cursor-pointer relative h-12 rounded-md px-8 text-sm font-medium transition-all w-full md:w-auto min-w-[240px]\",\n config.bgClass,\n className\n );\n\n // Animation variants\n const getAnimationProps = () => {\n switch (animation) {\n case \"scale\":\n return {\n whileHover: { scale: 1.02 },\n whileTap: { scale: 0.98 },\n };\n case \"slide\":\n return {}; // Handled via CSS/State inside\n default:\n return {\n whileTap: { scale: 0.98 },\n };\n }\n };\n\n return (\n <motion.div {...getAnimationProps()} className=\"relative group/social inline-block\">\n {/* Glow Effect */}\n {animation === \"glow\" && (\n <div className=\"absolute inset-0 rounded-md bg-current opacity-0 blur-lg group-hover/social:opacity-40 transition-opacity duration-500 text-inherit\" />\n )}\n\n <Button className={cn(baseStyles, \"overflow-hidden\")} {...props}>\n {/* Shine Effect */}\n {animation === \"shine\" && (\n <div className=\"absolute inset-0 -translate-x-full group-hover/social:translate-x-full transition-transform duration-1000 bg-gradient-to-r from-transparent via-white/20 to-transparent z-10 ease-in-out\" />\n )}\n\n <div className=\"flex items-center justify-center gap-3 w-full relative z-10\">\n <motion.span\n className={cn(\n \"flex-shrink-0\",\n animation === \"slide\" &&\n \"transition-transform duration-300 group-hover/social:-translate-x-1\"\n )}\n >\n <Icon className=\"w-5 h-5\" />\n </motion.span>\n <span\n className={cn(\n animation === \"slide\" &&\n \"transition-transform duration-300 group-hover/social:translate-x-1\"\n )}\n >\n {children || config.label}\n </span>\n </div>\n </Button>\n </motion.div>\n );\n};\n\nexport { SocialLoginButton };\n",
"type": "registry:component",
"target": "components/uitripled/social-login-button.tsx"
}
]
}

View file

@ -1315,7 +1315,7 @@
],
"files": [
{
"path": "@uitripled/react-baseui/src/components/components/stocks-dashboard/dashboard.tsx",
"path": "@uitripled/react-baseui/src/components/stocks-dashboard/dashboard-baseui.tsx",
"type": "registry:block",
"target": "components/uitripled/dashboard-baseui.tsx"
}
@ -1900,6 +1900,46 @@
"category": "components",
"subcategory": "modal"
},
{
"name": "folder-animation",
"type": "registry:ui",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:ui",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "decorative",
"subcategory": null
},
{
"name": "folder-animation-carbon",
"type": "registry:component",
"title": "Folder Animation",
"description": "Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.",
"registryDependencies": [],
"dependencies": [
"framer-motion",
"react"
],
"files": [
{
"path": "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
"type": "registry:component",
"target": "components/uitripled/folder-animation-carbon.tsx"
}
],
"category": "native",
"subcategory": null
},
{
"name": "footer-block-baseui",
"type": "registry:block",
@ -4472,7 +4512,7 @@
"name": "native-user-card-baseui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations. (Base UI)",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations (Base UI)",
"registryDependencies": [
"button"
],
@ -4487,14 +4527,14 @@
"target": "components/uitripled/native-user-card-baseui.tsx"
}
],
"category": "native",
"category": "cards",
"subcategory": null
},
{
"name": "native-user-card-shadcnui",
"type": "registry:component",
"title": "Native User Card",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations.",
"description": "Compact user profile card with avatar, name, handle, and action button with spring animations",
"registryDependencies": [],
"dependencies": [
"framer-motion",
@ -4507,7 +4547,7 @@
"target": "components/uitripled/native-user-card-shadcnui.tsx"
}
],
"category": "native",
"category": "cards",
"subcategory": null
},
{

View file

@ -77,6 +77,17 @@ import {
NativeFlipTextColored,
NativeFlipTextDefault,
} from "@uitripled/react-carbon/src/components/native/carbon/demo/native-flip-text-demo";
import {
FolderAnimationCustomIcon,
FolderAnimationDefault,
FolderAnimationFast,
FolderAnimationImageIcon,
FolderAnimationMusicIcon,
FolderAnimationNoFooter,
FolderAnimationSlow,
FolderAnimationWithActions,
} from "@uitripled/react-carbon/src/components/native/demo/folder-animation-demo";
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon";
import {
NativeHoverCardBordered,
NativeHoverCardCustomButton,
@ -2697,4 +2708,171 @@ export const nativeComponents: Component[] = [
display: true,
availableIn: ["shadcnui", "baseui"],
},
{
id: "folder-animation",
name: "Folder Animation",
description:
"Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.",
category: "native",
tags: ["folder", "animation", "motion", "blur", "card", "file", "native"],
component: FolderAnimation,
variants: [
{
id: "default",
name: "Default",
description: "Standard folder animation with footer content",
component: FolderAnimationDefault,
code: `<FolderAnimation>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Organizing Your Files</h3>
<p className="text-sm text-muted-foreground">
Watch as files seamlessly move through your workspace.
</p>
</div>
</FolderAnimation>`,
},
{
id: "fast",
name: "Fast",
description: "Faster animation cycle (2 seconds)",
component: FolderAnimationFast,
code: `<FolderAnimation animationDuration={2}>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Quick Transfer</h3>
<p className="text-sm text-muted-foreground">
Faster animation for quick file operations.
</p>
</div>
</FolderAnimation>`,
},
{
id: "slow",
name: "Slow",
description: "Slower animation cycle (6 seconds)",
component: FolderAnimationSlow,
code: `<FolderAnimation animationDuration={6}>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Careful Handling</h3>
<p className="text-sm text-muted-foreground">
Slower animation for detailed file processing.
</p>
</div>
</FolderAnimation>`,
},
{
id: "custom-icon",
name: "Custom (Doc)",
description: "Custom document icon",
component: FolderAnimationCustomIcon,
code: `<FolderAnimation
folderIcon={
<div className="w-24 h-24 bg-gradient-to-br from-blue-500 to-blue-700 rounded-xl flex items-center justify-center shadow-2xl">
<FileText className="w-12 h-12 text-white" />
</div>
}
>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Document Processing</h3>
<p className="text-sm text-muted-foreground">
Custom icon for document-specific operations.
</p>
</div>
</FolderAnimation>`,
},
{
id: "image-icon",
name: "Custom (Image)",
description: "Custom image gallery icon",
component: FolderAnimationImageIcon,
code: `<FolderAnimation
folderIcon={
<div className="w-28 h-24 bg-gradient-to-br from-purple-500 to-pink-500 rounded-xl flex items-center justify-center shadow-2xl overflow-hidden">
<Image className="w-12 h-12 text-white" />
</div>
}
>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Image Gallery</h3>
<p className="text-sm text-muted-foreground">
Organizing your photos with style.
</p>
</div>
</FolderAnimation>`,
},
{
id: "music-icon",
name: "Custom (Music)",
description: "Custom music library icon with circular shape",
component: FolderAnimationMusicIcon,
code: `<FolderAnimation
folderIcon={
<div className="w-24 h-24 bg-gradient-to-br from-green-500 to-emerald-600 rounded-full flex items-center justify-center shadow-2xl">
<Music className="w-10 h-10 text-white" />
</div>
}
animationDuration={3}
>
<div className="space-y-2">
<h3 className="font-semibold text-lg">Music Library</h3>
<p className="text-sm text-muted-foreground">
Your audio files in motion.
</p>
</div>
</FolderAnimation>`,
},
{
id: "with-actions",
name: "With Actions",
description: "Animation card with action buttons in footer",
component: FolderAnimationWithActions,
code: `<FolderAnimation>
<div className="space-y-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center">
<Folder className="w-5 h-5 text-primary" />
</div>
<div className="flex-1">
<h3 className="font-semibold">File Transfer in Progress</h3>
<p className="text-xs text-muted-foreground">
Moving 24 files to destination
</p>
</div>
</div>
<div className="flex gap-2">
<Button variant="outline" size="sm" className="flex-1">
Cancel
</Button>
<Button size="sm" className="flex-1">
View Details
</Button>
</div>
</div>
</FolderAnimation>`,
},
{
id: "no-footer",
name: "No Footer",
description: "Animation without footer content",
component: FolderAnimationNoFooter,
code: `<FolderAnimation />`,
},
],
codePath: "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
duration: "4000ms",
easing: "easeInOut",
display: true,
availableIn: ["carbon"],
},
{
id: "folder-animation-carbon",
name: "Folder Animation",
description:
"Animated folder card with motion blur effect, perfect for showcasing file operations or loading states.",
category: "native",
tags: [],
component: FolderAnimation,
codePath: "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
display: false,
availableIn: ["carbon"],
},
];

View file

@ -173,6 +173,7 @@ import { VolumeComponent } from "@uitripled/react-shadcn/src/components/componen
import { LiquidCursor } from "@uitripled/react-shadcn/src/components/liquid-cursor";
import { BrowseFolder } from "@uitripled/react-shadcn/src/components/sections/browse-folder";
import { GlowyWavesHero } from "@uitripled/react-shadcn/src/components/sections/glowy-waves-hero";
import { FolderAnimation } from "@uitripled/react-carbon/src/components/native/folder-animation-carbon";
import { WebPerformancePage } from "@uitripled/react-shadcn/src/components/web-performance/web-performance-page";
export const uiComponents: Component[] = [
@ -2380,4 +2381,18 @@ export const uiComponents: Component[] = [
display: true,
availableIn: ["shadcnui", "baseui"],
},
{
id: "folder-animation",
name: "Folder Animation",
description:
"Animated folder card with motion blur effect, perfect for showcasing file operations or loading states",
category: "decorative",
tags: ["folder", "animation", "motion", "blur", "card", "file"],
component: FolderAnimation,
codePath: "@uitripled/react-carbon/src/components/native/folder-animation-carbon.tsx",
duration: "4000ms",
easing: "easeInOut",
display: true,
availableIn: ["carbon"],
},
];