Dial Examples
Real-world examples demonstrating various use cases of the Dial system.
3D Object Controller
A complete example for controlling 3D objects with transform, appearance, and physics properties.
// Box3D.tsx
type Vector3 = [number, number, number];
type Quaternion = [number, number, number, number];
interface Box3DProps {
/**
* Position in world space
* @dial transform
* @dial-dtype vector3
* @dial-min -100
* @dial-max 100
* @dial-step 0.1
* @dial-icon Move3d
* @dial-label World Position
*/
position: Vector3;
/**
* Rotation (Euler angles in degrees)
* @dial transform
* @dial-dtype euler
* @dial-min -180
* @dial-max 180
* @dial-step 1
* @dial-icon RotateCw
*/
rotation: Vector3;
/**
* Scale factor
* @dial transform
* @dial-dtype vector3
* @dial-min 0.1
* @dial-max 10
* @dial-step 0.1
* @dial-icon Scaling
*/
scale: Vector3;
/**
* Box dimensions
* @dial geometry
* @dial-layout grid
* @dial-cols 3
* @dial-dtype vector
* @dial-mins [0.1, 0.1, 0.1]
* @dial-maxs [20, 20, 20]
* @dial-steps [0.1, 0.1, 0.1]
* @dial-placeholders ["Width", "Height", "Depth"]
* @dial-icon Box
*/
size: Vector3;
/**
* Number of segments
* @dial geometry
* @dial-dtype vector
* @dial-mins [1, 1, 1]
* @dial-maxs [32, 32, 32]
* @dial-steps [1, 1, 1]
* @dial-dtypes ["int", "int", "int"]
* @dial-placeholders ["W Segments", "H Segments", "D Segments"]
* @dial-icon Grid3x3
*/
segments: [number, number, number];
/**
* Base color
* @dial appearance
* @dial-dtype color
* @dial-icon Palette
* @dial-label Base Color
*/
color: string;
/**
* Emissive color
* @dial appearance
* @dial-dtype color
* @dial-icon Lightbulb
* @dial-label Emissive
*/
emissive: string;
/**
* Material type
* @dial appearance
* @dial-dtype select
* @dial-options ["standard", "physical", "lambert", "phong", "toon"]
* @dial-icon Sparkles
*/
material: string;
/**
* Metalness (for physical material)
* @dial appearance
* @dial-min 0
* @dial-max 1
* @dial-step 0.01
* @dial-icon Gem
*/
metalness: number;
/**
* Roughness (for physical material)
* @dial appearance
* @dial-min 0
* @dial-max 1
* @dial-step 0.01
* @dial-icon Brush
*/
roughness: number;
/**
* Opacity
* @dial appearance
* @dial-min 0
* @dial-max 1
* @dial-step 0.01
* @dial-icon Opacity
*/
opacity: number;
/**
* Cast shadows
* @dial rendering
* @dial-dtype boolean
* @dial-icon Moon
*/
castShadow: boolean;
/**
* Receive shadows
* @dial rendering
* @dial-dtype boolean
* @dial-icon Sun
*/
receiveShadow: boolean;
/**
* Visible
* @dial rendering
* @dial-dtype boolean
* @dial-icon Eye
*/
visible: boolean;
/**
* Enable physics
* @dial physics
* @dial-dtype boolean
* @dial-icon Zap
* @dial-label Enable Physics
*/
usePhysics: boolean;
/**
* Mass (kg)
* @dial physics
* @dial-min 0.1
* @dial-max 1000
* @dial-step 0.1
* @dial-icon Weight
*/
mass: number;
/**
* Friction coefficient
* @dial physics
* @dial-min 0
* @dial-max 1
* @dial-step 0.01
* @dial-icon Grip
*/
friction: number;
/**
* Restitution (bounciness)
* @dial physics
* @dial-min 0
* @dial-max 1
* @dial-step 0.01
* @dial-icon ArrowBounce
*/
restitution: number;
}
export const Box3D: React.FC<Box3DProps> = (props) => {
// Your 3D rendering logic here
return <mesh {...props} />;
};
UI Theme Editor
Control theme variables for a design system.
// ThemeEditor.tsx
type ColorRGB = [
// @dial-min 0 @dial-max 255 @dial-step 1 @dial-dtype int
r: number,
// @dial-min 0 @dial-max 255 @dial-step 1 @dial-dtype int
g: number,
// @dial-min 0 @dial-max 255 @dial-step 1 @dial-dtype int
b: number,
];
interface ThemeProps {
/**
* Primary brand color
* @dial colors
* @dial-dtype color
* @dial-icon Palette
* @dial-label Primary Color
*/
primaryColor: string;
/**
* Secondary brand color
* @dial colors
* @dial-dtype color
* @dial-icon Palette
* @dial-label Secondary Color
*/
secondaryColor: string;
/**
* Accent color
* @dial colors
* @dial-dtype color
* @dial-icon Star
* @dial-label Accent Color
*/
accentColor: string;
/**
* Background color (RGB values)
* @dial colors
* @dial-icon PaintBucket
* @dial-label Background RGB
*/
backgroundColor: ColorRGB;
/**
* Base font size
* @dial typography
* @dial-dtype int
* @dial-min 12
* @dial-max 24
* @dial-step 1
* @dial-icon Type
* @dial-label Base Font Size
*/
baseFontSize: number;
/**
* Line height multiplier
* @dial typography
* @dial-min 1
* @dial-max 2
* @dial-step 0.1
* @dial-icon AlignJustify
*/
lineHeight: number;
/**
* Font weight
* @dial typography
* @dial-dtype select
* @dial-options ["100", "200", "300", "400", "500", "600", "700", "800", "900"]
* @dial-icon Bold
*/
fontWeight: string;
/**
* Border radius
* @dial layout
* @dial-layout grid
* @dial-cols 2
* @dial-dtype int
* @dial-min 0
* @dial-max 32
* @dial-step 1
* @dial-icon RoundedCorner
* @dial-label Corner Radius
*/
borderRadius: number;
/**
* Spacing unit
* @dial layout
* @dial-dtype int
* @dial-min 2
* @dial-max 16
* @dial-step 1
* @dial-icon Ruler
* @dial-label Spacing Unit
*/
spacingUnit: number;
/**
* Enable dark mode
* @dial preferences
* @dial-dtype boolean
* @dial-icon Moon
*/
darkMode: boolean;
/**
* Enable animations
* @dial preferences
* @dial-dtype boolean
* @dial-icon Sparkles
*/
enableAnimations: boolean;
/**
* Animation duration (ms)
* @dial preferences
* @dial-dtype int
* @dial-min 100
* @dial-max 2000
* @dial-step 50
* @dial-icon Clock
*/
animationDuration: number;
}
Data Visualization Controls
Configure chart and graph properties.
// ChartControls.tsx
interface ChartProps {
/**
* Chart type
* @dial chart
* @dial-dtype select
* @dial-options ["line", "bar", "pie", "scatter", "area", "bubble"]
* @dial-icon BarChart
* @dial-label Chart Type
*/
type: string;
/**
* Chart title
* @dial chart
* @dial-dtype string
* @dial-icon Type
*/
title: string;
/**
* Show legend
* @dial chart
* @dial-dtype boolean
* @dial-icon List
*/
showLegend: boolean;
/**
* X-axis range
* @dial axes
* @dial-layout grid
* @dial-cols 2
* @dial-dtype vector2
* @dial-mins [-1000, -1000]
* @dial-maxs [1000, 1000]
* @dial-steps [1, 1]
* @dial-placeholders ["Min", "Max"]
* @dial-icon ArrowLeftRight
* @dial-label X-Axis Range
*/
xRange: [number, number];
/**
* Y-axis range
* @dial axes
* @dial-dtype vector2
* @dial-mins [-1000, -1000]
* @dial-maxs [1000, 1000]
* @dial-steps [1, 1]
* @dial-placeholders ["Min", "Max"]
* @dial-icon ArrowUpDown
* @dial-label Y-Axis Range
*/
yRange: [number, number];
/**
* Grid color
* @dial styling
* @dial-dtype color
* @dial-icon Grid3x3
*/
gridColor: string;
/**
* Line thickness
* @dial styling
* @dial-dtype int
* @dial-min 1
* @dial-max 10
* @dial-step 1
* @dial-icon Minus
*/
lineWidth: number;
/**
* Point size
* @dial styling
* @dial-dtype int
* @dial-min 1
* @dial-max 20
* @dial-step 1
* @dial-icon Circle
*/
pointSize: number;
/**
* Animation enabled
* @dial animation
* @dial-dtype boolean
* @dial-icon Play
*/
animated: boolean;
/**
* Animation duration (seconds)
* @dial animation
* @dial-min 0.1
* @dial-max 5
* @dial-step 0.1
* @dial-icon Timer
*/
animationDuration: number;
}
Game Settings Panel
Configure game parameters and difficulty settings.
// GameSettings.tsx
interface GameSettingsProps {
/**
* Difficulty level
* @dial gameplay
* @dial-dtype select
* @dial-options ["easy", "normal", "hard", "extreme"]
* @dial-icon Gamepad2
* @dial-label Difficulty
*/
difficulty: string;
/**
* Player speed
* @dial player
* @dial-min 1
* @dial-max 20
* @dial-step 0.5
* @dial-icon Zap
*/
playerSpeed: number;
/**
* Jump height
* @dial player
* @dial-min 1
* @dial-max 10
* @dial-step 0.5
* @dial-icon ArrowUp
*/
jumpHeight: number;
/**
* Health points
* @dial player
* @dial-dtype int
* @dial-min 1
* @dial-max 200
* @dial-step 1
* @dial-icon Heart
*/
health: number;
/**
* Master volume
* @dial audio
* @dial-layout grid
* @dial-cols 2
* @dial-min 0
* @dial-max 100
* @dial-step 1
* @dial-icon Volume2
*/
masterVolume: number;
/**
* Music volume
* @dial audio
* @dial-min 0
* @dial-max 100
* @dial-step 1
* @dial-icon Music
*/
musicVolume: number;
/**
* SFX volume
* @dial audio
* @dial-min 0
* @dial-max 100
* @dial-step 1
* @dial-icon AudioWaveform
*/
sfxVolume: number;
/**
* Enable voice chat
* @dial audio
* @dial-dtype boolean
* @dial-icon Mic
*/
voiceChat: boolean;
/**
* Graphics quality
* @dial graphics
* @dial-dtype select
* @dial-options ["low", "medium", "high", "ultra"]
* @dial-icon Monitor
*/
graphicsQuality: string;
/**
* Resolution scale
* @dial graphics
* @dial-min 50
* @dial-max 200
* @dial-step 10
* @dial-icon Maximize
*/
resolutionScale: number;
/**
* Enable shadows
* @dial graphics
* @dial-dtype boolean
* @dial-icon Moon
*/
shadows: boolean;
/**
* Anti-aliasing
* @dial graphics
* @dial-dtype select
* @dial-options ["none", "FXAA", "TAA", "MSAA x2", "MSAA x4", "MSAA x8"]
* @dial-icon Brush
*/
antiAliasing: string;
}
Usage with Generated Schema
After generating schemas with the CLI, integrate them into your application:
// App.tsx
import React, { useState } from 'react';
import { DialProvider, DialPanel } from '@vuer-ai/vuer-uikit';
import { Box3D } from './Box3D';
import dialSchemas from './metadata/schema.dial';
// Extract the Box3D schema
const box3DSchema = dialSchemas.find(s => s.component === 'Box3D');
function App() {
const [box3DProps, setBox3DProps] = useState({
position: [0, 0, 0],
rotation: [0, 0, 0],
scale: [1, 1, 1],
size: [1, 1, 1],
segments: [1, 1, 1],
color: '#3b82f6',
emissive: '#000000',
material: 'standard',
metalness: 0,
roughness: 0.5,
opacity: 1,
castShadow: true,
receiveShadow: true,
visible: true,
usePhysics: false,
mass: 1,
friction: 0.5,
restitution: 0.5
});
const handleValueChange = (name: string, value: any) => {
setBox3DProps(prev => ({ ...prev, [name]: value }));
};
return (
<div className="flex">
<div className="w-1/3 p-4">
<h2>3D Box Controls</h2>
<DialProvider
schemas={box3DSchema.schemas}
onValueChange={handleValueChange}
>
<DialPanel
schemas={box3DSchema.schemas}
groups={box3DSchema.groups}
/>
</DialProvider>
</div>
<div className="w-2/3 p-4">
<h2>3D Preview</h2>
<Box3D {...box3DProps} />
</div>
</div>
);
}
Best Practices
1. Group Related Properties
Organize properties into logical groups for better UX:
// Good: Grouped by concern
interface Props {
/** @dial transform */
x: number;
/** @dial transform */
y: number;
/** @dial appearance */
color: string;
/** @dial appearance */
opacity: number;
}
2. Use Descriptive Labels
Provide clear labels for better understanding:
interface Props {
/**
* @dial settings
* @dial-label "Maximum Retry Attempts"
*/
maxRetries: number;
/**
* @dial settings
* @dial-label "Connection Timeout (seconds)"
*/
timeout: number;
}
3. Set Appropriate Constraints
Define sensible min/max values:
interface Props {
/**
* @dial performance
* @dial-min 1
* @dial-max 120
* @dial-step 1
* @dial-label "Target FPS"
*/
targetFPS: number;
}
4. Use Icons for Visual Clarity
Add icons to improve visual recognition:
interface Props {
/** @dial controls @dial-icon Play */
play: boolean;
/** @dial controls @dial-icon Pause */
pause: boolean;
/** @dial controls @dial-icon SkipForward */
next: boolean;
}