Agent skill
control panel
Creates a control panel that allows runtime modification of values. When Claude needs to expose controls for the user to adjust variables and values.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/control-panel-toddmoy-protobox
SKILL.md
Leva Control Panel Skill
You are a specialized expert in creating interactive control panels using Leva - a React GUI library for building powerful, real-time controls for prototyping and debugging.
Available Tools in This Repo
Leva
Already installed via leva@^0.10.1. Import as:
import { useControls, button, folder, buttonGroup, LevaPanel } from 'leva'
Core Concepts
- useControls Hook - Primary hook for creating controls
- Automatic Type Detection - Leva infers control types from initial values
- Folders & Organization - Group related controls for better UX
- Real-time Updates - Controls update React state automatically
- Transient Mode - Performance optimization for smooth interactions
Control Types Reference
1. Number Controls
Basic number:
const { count } = useControls({
count: 42
})
Number with constraints:
const { value } = useControls({
value: { value: 50, min: 0, max: 100, step: 5 }
})
With suffix/prefix:
const { temperature } = useControls({
temperature: { value: 72, min: 32, max: 100, suffix: '°F' }
})
2. String/Text Controls
Basic text:
const { name } = useControls({
name: 'Default Name'
})
Multiline text:
const { description } = useControls({
description: { value: 'Long text...', rows: 3 }
})
3. Boolean Controls
Simple checkbox:
const { enabled } = useControls({
enabled: true
})
4. Color Controls
Supports hex, rgb, hsl:
const { color } = useControls({
background: '#4c9aff',
textColor: { value: '#ffffff', label: 'Text' },
accent: 'rgb(255, 100, 150)'
})
5. Select/Dropdown Controls
Array options:
const { size } = useControls({
size: { value: 'medium', options: ['small', 'medium', 'large'] }
})
Object options (custom labels):
const { theme } = useControls({
theme: {
value: 'dark',
options: {
'Light Mode': 'light',
'Dark Mode': 'dark',
'Auto': 'auto'
}
}
})
6. Vector Controls
2D vectors:
const { position } = useControls({
position: { value: { x: 0, y: 0 }, step: 1 }
})
3D vectors:
const { position3D } = useControls({
position3D: { value: { x: 0, y: 0, z: 0 }, step: 1 }
})
With constraints:
const { scale } = useControls({
scale: { value: { x: 1, y: 1 }, min: 0.1, max: 3, step: 0.1 }
})
7. Interval/Range Controls
Range slider:
const { range } = useControls({
range: { value: [20, 80], min: 0, max: 100 }
})
8. Button Controls
Single button:
const controls = useControls({
'Click Me': button(() => {
console.log('Clicked!')
})
})
Button group:
import { buttonGroup } from 'leva'
const controls = useControls({
'Actions': buttonGroup({
Save: () => handleSave(),
Load: () => handleLoad(),
Delete: () => handleDelete()
})
})
9. Image/File Controls
const { image } = useControls({
image: { image: undefined }
})
10. Monitor (Read-only Display)
const { fps } = useControls({
'Current FPS': { value: currentFps, disabled: true }
})
Organization Patterns
Grouped Controls
const controls = useControls('Settings', {
width: 400,
height: 300,
color: '#ff0000'
})
Nested Folders
import { folder } from 'leva'
const controls = useControls('Advanced', {
'Animation': folder({
duration: { value: 1000, min: 100, max: 5000, step: 100 },
easing: { value: 'easeOut', options: ['linear', 'easeIn', 'easeOut'] },
loop: false
}),
'Performance': folder({
fps: { value: 60, min: 24, max: 120 },
quality: { value: 'high', options: ['low', 'medium', 'high'] }
}, { collapsed: true }) // Start collapsed
})
Advanced Features
1. Transient Mode (Performance)
Use for smooth real-time updates without re-renders:
const { value } = useControls({
value: {
value: 50,
min: 0,
max: 100,
transient: false // Set to true for onChange-only updates
}
})
Note: In Leva 0.10.1, transient mode is handled automatically - just use regular controls for smooth interactions.
2. Multiple Panels
import { LevaPanel, useControls } from 'leva'
function Component() {
const panel1 = useControls('Panel 1', { value1: 0 })
const panel2 = useControls('Panel 2', { value2: 100 })
return (
<>
<LevaPanel store={panel1} />
<LevaPanel store={panel2} />
</>
)
}
3. Conditional Controls
const { mode, detail } = useControls({
mode: { value: 'simple', options: ['simple', 'advanced'] },
...(mode === 'advanced' && {
detail: { value: 5, min: 1, max: 10 }
})
})
4. Custom Labels
const controls = useControls({
bgColor: { value: '#ffffff', label: 'Background Color' }
})
5. Control Order
const controls = useControls({
name: 'Title',
size: { value: 100, order: 0 }, // Appears first
color: { value: '#fff', order: 1 }, // Appears second
enabled: { value: true, order: 2 } // Appears third
})
Common Use Cases
1. Visual Prototype Controls
function PrototypeComponent() {
const { width, height, color, opacity, rounded } = useControls('Visual', {
width: { value: 200, min: 100, max: 800, step: 10 },
height: { value: 200, min: 100, max: 800, step: 10 },
color: '#4c9aff',
opacity: { value: 1, min: 0, max: 1, step: 0.01 },
rounded: { value: 8, min: 0, max: 50, step: 1, suffix: 'px' }
})
return (
<div
style={{
width,
height,
backgroundColor: color,
opacity,
borderRadius: rounded
}}
/>
)
}
2. Animation Controls
import { motion } from 'framer-motion'
function AnimatedComponent() {
const { duration, delay, x, y, scale, rotate } = useControls('Animation', {
duration: { value: 1, min: 0.1, max: 5, step: 0.1, suffix: 's' },
delay: { value: 0, min: 0, max: 2, step: 0.1, suffix: 's' },
x: { value: 0, min: -200, max: 200 },
y: { value: 0, min: -200, max: 200 },
scale: { value: 1, min: 0.1, max: 3, step: 0.1 },
rotate: { value: 0, min: 0, max: 360, suffix: '°' }
})
return (
<motion.div
animate={{ x, y, scale, rotate }}
transition={{ duration, delay }}
>
Animated Element
</motion.div>
)
}
3. Theme/Style Controls
function ThemedComponent() {
const { theme, spacing, fontSize, fontWeight } = useControls('Theme', {
theme: {
value: 'light',
options: { Light: 'light', Dark: 'dark', Auto: 'auto' }
},
spacing: { value: 'comfortable', options: ['compact', 'comfortable', 'spacious'] },
fontSize: { value: 16, min: 12, max: 24, step: 1, suffix: 'px' },
fontWeight: {
value: 400,
options: { Light: 300, Regular: 400, Medium: 500, Bold: 700 }
}
})
return <div style={{ fontSize, fontWeight }}>Styled Content</div>
}
4. Data Visualization Controls
function ChartComponent() {
const { dataPoints, chartType, showGrid, showLegend, colorScheme } = useControls('Chart', {
dataPoints: { value: 50, min: 10, max: 200, step: 10 },
chartType: { value: 'bar', options: ['line', 'bar', 'area', 'scatter'] },
showGrid: true,
showLegend: true,
colorScheme: {
value: 'default',
options: ['default', 'vibrant', 'pastel', 'monochrome']
}
})
// Render chart with these controls
}
5. Interactive Actions
import { button, buttonGroup } from 'leva'
function InteractiveComponent() {
const [state, setState] = useState('idle')
const controls = useControls('Actions', {
'Quick Actions': buttonGroup({
Reset: () => setState('idle'),
Start: () => setState('running'),
Pause: () => setState('paused'),
Stop: () => setState('stopped')
}),
'Export': button(() => {
// Export logic
console.log('Exporting...')
}),
'Current State': { value: state, disabled: true }
})
return <div>State: {state}</div>
}
Best Practices
- Group Related Controls - Use folders to organize complex UIs
- Provide Constraints - Always set min/max for numeric values when appropriate
- Use Descriptive Labels - Make control purposes clear
- Add Units - Use suffix/prefix for clarity (px, %, °, ms, etc.)
- Start Collapsed - Use
{ collapsed: true }for secondary options - Monitor Important Values - Use disabled controls to display computed values
- Use Button Groups - Group related actions together for better UX
- Keep It Organized - Don't create too many controls at the root level
- Performance - For real-time controls, Leva is already optimized
- Naming - Use clear, consistent naming conventions
Integration with Other Libraries
With Framer Motion
import { motion } from 'framer-motion'
import { useControls } from 'leva'
function AnimatedBox() {
const { x, y, rotate, scale } = useControls({
x: { value: 0, min: -200, max: 200 },
y: { value: 0, min: -200, max: 200 },
rotate: { value: 0, min: 0, max: 360 },
scale: { value: 1, min: 0.5, max: 2, step: 0.1 }
})
return (
<motion.div animate={{ x, y, rotate, scale }}>
Content
</motion.div>
)
}
With Three.js/React Three Fiber
import { useControls } from 'leva'
function Scene() {
const { intensity, position, color } = useControls('Light', {
intensity: { value: 1, min: 0, max: 5, step: 0.1 },
position: { value: { x: 0, y: 5, z: 0 } },
color: '#ffffff'
})
return (
<pointLight
intensity={intensity}
position={[position.x, position.y, position.z]}
color={color}
/>
)
}
Styling & Customization
The Leva panel appears by default in the top-right corner. It supports dark/light themes automatically based on system preferences.
For custom positioning or styling, use CSS:
/* Target the Leva root */
:root {
--leva-colors-accent1: #4c9aff;
--leva-colors-accent2: #5c6bc0;
}
Quick Reference
| Control Type | Input | Output |
|---|---|---|
| Number | count: 42 |
{ count: number } |
| String | name: 'text' |
{ name: string } |
| Boolean | enabled: true |
{ enabled: boolean } |
| Color | color: '#fff' |
{ color: string } |
| Select | size: { options: [...] } |
{ size: string } |
| Vector2D | pos: { x: 0, y: 0 } |
{ pos: {x, y} } |
| Vector3D | pos: { x, y, z } |
{ pos: {x, y, z} } |
| Range | range: [20, 80] |
{ range: [number, number] } |
| Button | button(() => {}) |
void |
| Image | image: { image } |
{ image: string | undefined } |
Example: Complete Control Panel
import { useControls, folder, button, buttonGroup } from 'leva'
import { motion } from 'framer-motion'
function CompleteDemo() {
const {
// Basic
name,
count,
enabled,
// Visual
color,
size,
opacity,
// Position
position,
// Advanced
duration,
easing,
quality
} = useControls({
// Basic group
name: 'Demo',
count: { value: 42, min: 0, max: 100 },
enabled: true,
// Visual group
Visual: folder({
color: '#4c9aff',
size: { value: 'medium', options: ['small', 'medium', 'large'] },
opacity: { value: 1, min: 0, max: 1, step: 0.01 }
}),
// Position
position: { value: { x: 0, y: 0 }, step: 5 },
// Advanced
Advanced: folder({
duration: { value: 1000, min: 100, max: 3000, suffix: 'ms' },
easing: { value: 'easeOut', options: ['linear', 'easeIn', 'easeOut'] },
quality: { value: 'high', options: ['low', 'medium', 'high'] }
}, { collapsed: true }),
// Actions
'Reset': button(() => console.log('Reset!')),
'Actions': buttonGroup({
Save: () => console.log('Save'),
Load: () => console.log('Load')
})
})
return (
<motion.div
style={{
backgroundColor: color,
opacity,
width: size === 'small' ? 100 : size === 'medium' ? 200 : 300
}}
animate={{ x: position.x, y: position.y }}
transition={{ duration: duration / 1000 }}
>
{name} - {count}
</motion.div>
)
}
When to Use Leva
✅ Use Leva when:
- Building interactive prototypes
- Debugging visual components
- Creating design system demos
- Fine-tuning animations
- Building configurators
- Creating interactive documentation
- Developing with React Three Fiber
❌ Don't use Leva for:
- Production user-facing forms (use proper form libraries)
- Complex validation requirements
- Multi-step wizards
- Data entry applications
Leva excels at rapid prototyping and real-time parameter tweaking during development!
Didn't find tool you were looking for?