Skip to main content
frontend-patterns Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.
Aller à l'installation Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/davila7/claude-code-templates --skill frontend-patternsLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Plus depuis ce dépôt Build AI agents that interact with computers like humans do - viewing screens, moving cursors, clicking buttons, and typing text. Covers Anthropic's Computer Use, OpenAI's Operator/CUA, and open-source alternatives. Critical focus on sandboxing, security, and handling the unique challenges of vision-based control. Use when: computer use, desktop automation agent, screen control AI, vision-based agent, GUI automation.
Expert in building products that wrap AI APIs (OpenAI, Anthropic, etc.) into focused tools people will pay for. Not just 'ChatGPT but different' - products that solve specific problems with AI. Covers prompt engineering for products, cost management, rate limiting, and building defensible AI businesses. Use when: AI wrapper, GPT product, AI tool, wrap AI, AI SaaS.
github-workflow-automation Automate GitHub workflows with AI assistance. Includes PR reviews, issue triage, CI/CD integration, and Git operations. Use when automating GitHub workflows, setting up PR review automation, creating GitHub Actions, or triaging issues.
Métiers associés SOC
Basé sur la classification professionnelle SOC
name frontend-patterns description Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices. author affaan-m version 1.0
Frontend Development Patterns
Modern frontend patterns for React, Next.js, and performant user interfaces.
Component Patterns
Composition Over Inheritance
interface CardProps {
children : React .ReactNode
variant ?: 'default' | 'outlined'
}
export function Card ({ children, variant = 'default' }: CardProps ) {
return <div className ={ `card card- ${ }`}> {children}
}
( ) {
}
( ) {
}
< >
</ >
variant
</div >
export
function
CardHeader
{ children }: { children: React.ReactNode }
return
<div className ="card-header" > {children}</div >
export
function
CardBody
{ children }: { children: React.ReactNode }
return
<div className ="card-body" > {children}</div >
Card
<CardHeader > Title</CardHeader >
<CardBody > Content</CardBody >
Card
Compound Components interface TabsContextValue {
activeTab : string
setActiveTab : (tab : string ) => void
}
const TabsContext = createContext<TabsContextValue | undefined >(undefined )
export function Tabs ({ children, defaultTab }: {
children: React.ReactNode
defaultTab: string
} ) {
const [activeTab, setActiveTab] = useState (defaultTab)
return (
<TabsContext.Provider value ={{ activeTab , setActiveTab }}>
{children}
</TabsContext.Provider >
)
}
export function TabList ({ children }: { children: React.ReactNode } ) {
return <div className ="tab-list" > {children}</div >
}
export function Tab ({ id, children }: { id: string , children: React.ReactNode } ) {
const context = useContext (TabsContext )
if (!context) throw new Error ('Tab must be used within Tabs' )
return (
<button
className ={context.activeTab === id ? 'active ' : ''}
onClick ={() => context.setActiveTab(id)}
>
{children}
</button >
)
}
<Tabs defaultTab="overview" >
<TabList >
<Tab id ="overview" > Overview</Tab >
<Tab id ="details" > Details</Tab >
</TabList >
</Tabs >
Render Props Pattern interface DataLoaderProps <T> {
url : string
children : (data : T | null , loading : boolean , error : Error | null ) => React .ReactNode
}
export function DataLoader <T>({ url, children }: DataLoaderProps <T>) {
const [data, setData] = useState<T | null >(null )
const [loading, setLoading] = useState (true )
const [error, setError] = useState<Error | null >(null )
useEffect (() => {
fetch (url)
.then (res => res.json ())
.then (setData)
.catch (setError)
.finally (() => setLoading (false ))
}, [url])
return <> {children(data, loading, error)}</>
}
<DataLoader <Market []> url="/api/markets" >
{(markets, loading, error ) => {
if (loading) return <Spinner />
if (error) return <Error error ={error} />
return <MarketList markets ={markets!} />
}}
</DataLoader >
Custom Hooks Patterns
State Management Hook export function useToggle (initialValue = false ): [boolean , () => void ] {
const [value, setValue] = useState (initialValue)
const toggle = useCallback (() => {
setValue (v => !v)
}, [])
return [value, toggle]
}
const [isOpen, toggleOpen] = useToggle ()
Async Data Fetching Hook interface UseQueryOptions <T> {
onSuccess ?: (data : T ) => void
onError ?: (error : Error ) => void
enabled ?: boolean
}
export function useQuery<T>(
key : string ,
fetcher : () => Promise <T>,
options ?: UseQueryOptions <T>
) {
const [data, setData] = useState<T | null >(null )
const [error, setError] = useState<Error | null >(null )
const [loading, setLoading] = useState (false )
const refetch = useCallback (async () => {
setLoading (true )
setError (null )
try {
const result = await fetcher ()
setData (result)
options?.onSuccess ?.(result)
} catch (err) {
const error = err as Error
setError (error)
options?.onError ?.(error)
} finally {
setLoading (false )
}
}, [fetcher, options])
useEffect (() => {
if (options?.enabled !== false ) {
refetch ()
}
}, [key, refetch, options?.enabled ])
return { data, error, loading, refetch }
}
const { data : markets, loading, error, refetch } = useQuery (
'markets' ,
() => fetch ('/api/markets' ).then (r => r.json ()),
{
onSuccess : data => console .log ('Fetched' , data.length , 'markets' ),
onError : err => console .error ('Failed:' , err)
}
)
Debounce Hook export function useDebounce<T>(value : T, delay : number ): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect (() => {
const handler = setTimeout (() => {
setDebouncedValue (value)
}, delay)
return () => clearTimeout (handler)
}, [value, delay])
return debouncedValue
}
const [searchQuery, setSearchQuery] = useState ('' )
const debouncedQuery = useDebounce (searchQuery, 500 )
useEffect (() => {
if (debouncedQuery) {
performSearch (debouncedQuery)
}
}, [debouncedQuery])
State Management Patterns
Context + Reducer Pattern interface State {
markets : Market []
selectedMarket : Market | null
loading : boolean
}
type Action =
| { type : 'SET_MARKETS' ; payload : Market [] }
| { type : 'SELECT_MARKET' ; payload : Market }
| { type : 'SET_LOADING' ; payload : boolean }
function reducer (state : State , action : Action ): State {
switch (action.type ) {
case 'SET_MARKETS' :
return { ...state, markets : action.payload }
case 'SELECT_MARKET' :
return { ...state, selectedMarket : action.payload }
case 'SET_LOADING' :
return { ...state, loading : action.payload }
default :
return state
}
}
const MarketContext = createContext<{
state : State
dispatch : Dispatch <Action >
} | undefined >(undefined )
export function MarketProvider ({ children }: { children: React.ReactNode } ) {
const [state, dispatch] = useReducer (reducer, {
markets : [],
selectedMarket : null ,
loading : false
})
return (
<MarketContext.Provider value ={{ state , dispatch }}>
{children}
</MarketContext.Provider >
)
}
export function useMarkets ( ) {
const context = useContext (MarketContext )
if (!context) throw new Error ('useMarkets must be used within MarketProvider' )
return context
}
Performance Optimization
Memoization
const sortedMarkets = useMemo (() => {
return markets.sort ((a, b ) => b.volume - a.volume )
}, [markets])
const handleSearch = useCallback ((query : string ) => {
setSearchQuery (query)
}, [])
export const MarketCard = React .memo <MarketCardProps >(({ market } ) => {
return (
<div className ="market-card" >
<h3 > {market.name}</h3 >
<p > {market.description}</p >
</div >
)
})
Code Splitting & Lazy Loading import { lazy, Suspense } from 'react'
const HeavyChart = lazy (() => import ('./HeavyChart' ))
const ThreeJsBackground = lazy (() => import ('./ThreeJsBackground' ))
export function Dashboard ( ) {
return (
<div >
<Suspense fallback ={ <ChartSkeleton /> }>
<HeavyChart data ={data} />
</Suspense >
<Suspense fallback ={null} >
<ThreeJsBackground />
</Suspense >
</div >
)
}
Virtualization for Long Lists import { useVirtualizer } from '@tanstack/react-virtual'
export function VirtualMarketList ({ markets }: { markets: Market[] } ) {
const parentRef = useRef<HTMLDivElement >(null )
const virtualizer = useVirtualizer ({
count : markets.length ,
getScrollElement : () => parentRef.current ,
estimateSize : () => 100 ,
overscan : 5
})
return (
<div ref ={parentRef} style ={{ height: '600px ', overflow: 'auto ' }}>
<div
style ={{
height: `${virtualizer.getTotalSize ()}px `,
position: 'relative '
}}
>
{virtualizer.getVirtualItems().map(virtualRow => (
<div
key ={virtualRow.index}
style ={{
position: 'absolute ',
top: 0 ,
left: 0 ,
width: '100 %',
height: `${virtualRow.size }px `,
transform: `translateY (${virtualRow.start }px )`
}}
>
<MarketCard market ={markets[virtualRow.index]} />
</div >
))}
</div >
</div >
)
}
Form Handling Patterns
Controlled Form with Validation interface FormData {
name : string
description : string
endDate : string
}
interface FormErrors {
name ?: string
description ?: string
endDate ?: string
}
export function CreateMarketForm ( ) {
const [formData, setFormData] = useState<FormData >({
name : '' ,
description : '' ,
endDate : ''
})
const [errors, setErrors] = useState<FormErrors >({})
const validate = (): boolean => {
const newErrors : FormErrors = {}
if (!formData.name .trim ()) {
newErrors.name = 'Name is required'
} else if (formData.name .length > 200 ) {
newErrors.name = 'Name must be under 200 characters'
}
if (!formData.description .trim ()) {
newErrors.description = 'Description is required'
}
if (!formData.endDate ) {
newErrors.endDate = 'End date is required'
}
setErrors (newErrors)
return Object .keys (newErrors).length === 0
}
const handleSubmit = async (e : React .FormEvent ) => {
e.preventDefault ()
if (!validate ()) return
try {
await createMarket (formData)
} catch (error) {
}
}
return (
<form onSubmit ={handleSubmit} >
<input
value ={formData.name}
onChange ={e => setFormData(prev => ({ ...prev, name: e.target.value }))}
placeholder="Market name"
/>
{errors.name && <span className ="error" > {errors.name}</span > }
{/* Other fields */}
<button type ="submit" > Create Market</button >
</form >
)
}
Error Boundary Pattern interface ErrorBoundaryState {
hasError : boolean
error : Error | null
}
export class ErrorBoundary extends React.Component <
{ children : React .ReactNode },
ErrorBoundaryState
> {
state : ErrorBoundaryState = {
hasError : false ,
error : null
}
static getDerivedStateFromError (error : Error ): ErrorBoundaryState {
return { hasError : true , error }
}
componentDidCatch (error : Error , errorInfo : React .ErrorInfo ) {
console .error ('Error boundary caught:' , error, errorInfo)
}
render ( ) {
if (this .state .hasError ) {
return (
<div className ="error-fallback" >
<h2 > Something went wrong</h2 >
<p > {this.state.error?.message}</p >
<button onClick ={() => this.setState({ hasError: false })}>
Try again
</button >
</div >
)
}
return this .props .children
}
}
<ErrorBoundary >
<App />
</ErrorBoundary >
Animation Patterns
Framer Motion Animations import { motion, AnimatePresence } from 'framer-motion'
export function AnimatedMarketList ({ markets }: { markets: Market[] } ) {
return (
<AnimatePresence >
{markets.map(market => (
<motion.div
key ={market.id}
initial ={{ opacity: 0 , y: 20 }}
animate ={{ opacity: 1 , y: 0 }}
exit ={{ opacity: 0 , y: -20 }}
transition ={{ duration: 0.3 }}
>
<MarketCard market ={market} />
</motion.div >
))}
</AnimatePresence >
)
}
export function Modal ({ isOpen, onClose, children }: ModalProps ) {
return (
<AnimatePresence >
{isOpen && (
<>
<motion.div
className ="modal-overlay"
initial ={{ opacity: 0 }}
animate ={{ opacity: 1 }}
exit ={{ opacity: 0 }}
onClick ={onClose}
/>
<motion.div
className ="modal-content"
initial ={{ opacity: 0 , scale: 0.9 , y: 20 }}
animate ={{ opacity: 1 , scale: 1 , y: 0 }}
exit ={{ opacity: 0 , scale: 0.9 , y: 20 }}
>
{children}
</motion.div >
</>
)}
</AnimatePresence >
)
}
Accessibility Patterns
Keyboard Navigation export function Dropdown ({ options, onSelect }: DropdownProps ) {
const [isOpen, setIsOpen] = useState (false )
const [activeIndex, setActiveIndex] = useState (0 )
const handleKeyDown = (e : React .KeyboardEvent ) => {
switch (e.key ) {
case 'ArrowDown' :
e.preventDefault ()
setActiveIndex (i => Math .min (i + 1 , options.length - 1 ))
break
case 'ArrowUp' :
e.preventDefault ()
setActiveIndex (i => Math .max (i - 1 , 0 ))
break
case 'Enter' :
e.preventDefault ()
onSelect (options[activeIndex])
setIsOpen (false )
break
case 'Escape' :
setIsOpen (false )
break
}
}
return (
<div
role ="combobox"
aria-expanded ={isOpen}
aria-haspopup ="listbox"
onKeyDown ={handleKeyDown}
>
{/* Dropdown implementation */}
</div >
)
}
Focus Management export function Modal ({ isOpen, onClose, children }: ModalProps ) {
const modalRef = useRef<HTMLDivElement >(null )
const previousFocusRef = useRef<HTMLElement | null >(null )
useEffect (() => {
if (isOpen) {
previousFocusRef.current = document .activeElement as HTMLElement
modalRef.current ?.focus ()
} else {
previousFocusRef.current ?.focus ()
}
}, [isOpen])
return isOpen ? (
<div
ref ={modalRef}
role ="dialog"
aria-modal ="true"
tabIndex ={-1}
onKeyDown ={e => e.key === 'Escape' && onClose()}
>
{children}
</div >
) : null
}
Remember : Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.