# advanced-ui-patterns
> Advanced patterns like infinite scroll, drag-and-drop, virtualization, modals, portals, toast notifications, and complex interactions. Use when implementing advanced UI features, optimizing long lists, or creating rich interactions.
- Author: Nir
- Repository: Nirkoso/Nir-Claude
- Version: 20260126102449
- Stars: 0
- Forks: 0
- Last Updated: 2026-02-07
- Source: https://github.com/Nirkoso/Nir-Claude
- Web: https://mule.run/skillshub/@@Nirkoso/Nir-Claude~advanced-ui-patterns:20260126102449
---
---
name: advanced-ui-patterns
description: Advanced patterns like infinite scroll, drag-and-drop, virtualization, modals, portals, toast notifications, and complex interactions. Use when implementing advanced UI features, optimizing long lists, or creating rich interactions.
---
# Advanced UI Patterns
Implement sophisticated user interface patterns.
## 1. Infinite Scroll
```typescript
import { useInfiniteQuery } from '@tanstack/react-query';
import { useInView } from 'react-intersection-observer';
function InfiniteScroll() {
const { ref, inView } = useInView();
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage
} = useInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam = 0 }) => fetchPosts(pageParam),
getNextPageParam: (lastPage, pages) => lastPage.nextCursor
});
useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView, hasNextPage, fetchNextPage]);
return (
{data?.pages.map(page =>
page.items.map(item =>
)
)}
{isFetchingNextPage ? 'Loading...' : hasNextPage ? 'Load More' : 'No more items'}
);
}
```
## 2. Virtual Scrolling
```typescript
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }: { items: any[] }) {
const parentRef = useRef(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
overscan: 5
});
return (
{virtualizer.getVirtualItems().map(virtualItem => (
))}
);
}
```
## 3. Drag and Drop
```typescript
import { DndContext, useDraggable, useDroppable } from '@dnd-kit/core';
function Draggable({ id, children }: { id: string; children: React.ReactNode }) {
const { attributes, listeners, setNodeRef, transform } = useDraggable({ id });
const style = transform ? {
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
} : undefined;
return (
{children}
);
}
function Droppable({ id, children }: { id: string; children: React.ReactNode }) {
const { setNodeRef } = useDroppable({ id });
return {children}
;
}
function DragDropExample() {
const [items, setItems] = useState(['A', 'B', 'C']);
const handleDragEnd = (event: any) => {
const { active, over } = event;
if (over && active.id !== over.id) {
// Reorder items
const oldIndex = items.indexOf(active.id);
const newIndex = items.indexOf(over.id);
const newItems = arrayMove(items, oldIndex, newIndex);
setItems(newItems);
}
};
return (
{items.map(item => (
{item}
))}
);
}
```
## 4. Modal / Dialog with Portal
```typescript
import { createPortal } from 'react-dom';
function Modal({ isOpen, onClose, children }: ModalProps) {
const modalRef = useRef(null);
useEffect(() => {
if (!isOpen) return;
// Focus trap
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
if (e.key === 'Tab') {
const focusable = modalRef.current?.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
// Handle focus trap logic
}
};
document.addEventListener('keydown', handleKeyDown);
document.body.style.overflow = 'hidden';
return () => {
document.removeEventListener('keydown', handleKeyDown);
document.body.style.overflow = '';
};
}, [isOpen, onClose]);
if (!isOpen) return null;
return createPortal(
e.stopPropagation()}
>
{children}
,
document.body
);
}
```
## 5. Toast Notifications
```typescript
import { toast, Toaster } from 'react-hot-toast';
function App() {
return (
<>
>
);
}
// Custom toast
function CustomToast() {
return (
);
}
```
## 6. Command Palette
```typescript
import { useEffect, useState } from 'react';
function CommandPalette() {
const [isOpen, setIsOpen] = useState(false);
const [query, setQuery] = useState('');
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
setIsOpen(true);
}
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
const commands = [
{ name: 'New Post', action: () => {} },
{ name: 'Settings', action: () => {} },
{ name: 'Logout', action: () => {} }
];
const filtered = commands.filter(cmd =>
cmd.name.toLowerCase().includes(query.toLowerCase())
);
if (!isOpen) return null;
return (
);
}
```
## 7. Skeleton Loading
```typescript
function SkeletonCard() {
return (
);
}
function ContentWithSkeleton() {
const { data, isLoading } = useQuery({
queryKey: ['content'],
queryFn: fetchContent
});
if (isLoading) return ;
return ;
}
```
## Best Practices
1. **Virtual scrolling for large lists** - Render only visible items
2. **Intersection Observer** - Better than scroll events
3. **Portal for modals** - Avoid z-index issues
4. **Focus management** - Trap focus in modals
5. **Keyboard shortcuts** - Cmd+K for command palette
6. **Optimistic updates** - Update UI before server response
7. **Skeleton screens** - Better than spinners for content
8. **Debounce search** - Reduce API calls