Component Patterns
Overview
Studio implements several proven component patterns that enable developers to build consistent, maintainable analytics interfaces. These patterns provide reusable abstractions for common functionality.
Key component patterns used throughout Studio
Builder Components
Builder components enable complex form configuration through modular, composable interfaces.
Metric Schema Builder
The most complex builder pattern in Studio, orchestrating multiple sub-builders for metric configuration.
How MetricSchemaBuilder coordinates sub-builders
Architecture:
- Tabbed Interface: Organizes complex configuration into manageable sections
- Reactive Schema: Shared reactive schema object across all builders
- Validation Integration: Real-time validation with visual feedback
- Preview Mode: Live preview of metric configuration
Key Sub-Builders:
BasicInfoBuilder- Core metric information (name, description, table)MeasuresBuilder- Quantitative measurements and calculationsDimensionsBuilder- Categorical attributes for groupingJoinsBuilder- Table relationship definitionsFiltersBuilder- Data filtering conditionsAggregationsBuilder- Complex aggregation logicParametersBuilder- Runtime parameter configuration
Implementation Pattern:
// Shared reactive schema
const schema = reactive({
name: '',
description: '',
measures: [],
dimensions: [],
joins: [],
filters: [],
aggregations: [],
parameters: {}
})
// Each builder receives the schema section it manages
<MeasuresBuilder v-model="schema.measures" />
<DimensionsBuilder v-model="schema.dimensions" />
Dashboard Builder
Enables visual dashboard composition with drag-and-drop functionality.
Dashboard building workflow and component structure
Components:
DashboardContainer- Main dashboard layout and orchestrationDashboardSection- Grouped widget areas with drag-and-dropWidgetRenderer- Dynamic widget component renderingWidgetEditSheet- Widget configuration interfaceDataMappingEditor- Chart data mapping configuration
Features:
- Grid Layout: Responsive grid system for widget positioning
- Drag & Drop: FormKit drag-and-drop for widget arrangement
- Real-time Preview: Live dashboard execution and preview
- Widget Library: Extensible widget type system
Dialog Patterns
Consistent modal interfaces for all CRUD operations across Studio.
Standard CRUD Dialogs
Standardized create, edit, and delete dialog patterns
Dialog Types:
Create Dialogs
CreateWorkspaceDialog- New workspace creationCreateEnvironmentDialog- Environment setupCreateDataSourceDialog- Data source configurationCreateMetricDialog- Basic metric creationCreateConsumerDialog- Consumer management
Pattern:
// Consistent structure for create dialogs
interface CreateDialogProps {
open: boolean
prefilledData?: Partial<T>
}
interface CreateDialogEmits {
'update:open': (value: boolean) => void
'created': (item: T) => void
}
Edit Dialogs
EditWorkspaceDialog- Workspace modificationEditEnvironmentDialog- Environment updatesEditDataSourceDialog- Data source changesEditMetricDialog- Metric modifications
Pattern:
// Edit dialogs include item identification
interface EditDialogProps {
open: boolean
item: T
}
interface EditDialogEmits {
'update:open': (value: boolean) => void
'updated': (item: T) => void
}
Complex Dialogs
Advanced dialogs for multi-step workflows.
Multi-step dialog patterns for complex workflows
Examples:
MetricDialog- Full metric creation with schema builderWidgetUpsertDialog- Widget creation with chart configurationDashboardViewSelector- Dashboard view management
Features:
- Multi-step Flows: Tabbed or wizard-style interfaces
- Form Validation: Comprehensive validation with error display
- Auto-save: Draft saving for complex configurations
- Help Context: Contextual help and examples
Chart Component Patterns
Reusable visualization components with consistent APIs.
Base Chart Pattern
Base chart component structure and inheritance
Chart Types:
BarChart- Bar and column chartsLineChart- Line and area chartsDonutChart- Pie and donut chartsGauge- Gauge and KPI displaysSingleValue- Single metric displaysTable- Data table with sorting
Common Interface:
interface BaseChartProps {
data: any[]
height: number
config?: ChartConfig
loading?: boolean
}
interface ChartConfig {
colors?: string[]
legend?: boolean
grid?: boolean
responsive?: boolean
}
Chart Selector Pattern
Dynamic chart type selection with automatic data mapping.
How ChartSelector enables dynamic chart type switching
Features:
- Type Detection: Automatic chart type recommendations
- Field Mapping: Smart field mapping for X/Y axes
- Data Validation: Real-time validation of chart compatibility
- Preview Mode: Instant chart preview with configuration changes
Widget Pattern
Dashboard widgets that wrap charts with additional functionality.
Widget wrapper pattern for dashboard integration
Widget Types:
ChartWidget- Standard chart visualizationsSingleValueWidget- KPI and metric displaysGaugeWidget- Progress and target visualizationsTableWidget- Data table displays
Widget Features:
- Metric Integration: Direct metric execution and display
- Configuration UI: Built-in configuration interfaces
- Error Handling: Graceful error display and recovery
- Loading States: Skeleton loading for better UX
Form Patterns
Consistent form handling with validation and error management.
Validated Forms
Form validation pattern with VeeValidate and Zod
Implementation:
- Schema Validation: Zod schemas for type-safe validation
- Real-time Feedback: Immediate validation on field changes
- Error Display: Consistent error message presentation
- Field Dependencies: Cross-field validation and dependencies
Example Pattern:
// Form schema definition
const formSchema = z.object({
name: z.string().min(1, 'Name is required'),
description: z.string().optional(),
type: z.enum(['bar', 'line', 'pie'])
})
// Form state management
const { values, errors, isValid } = useForm({
validationSchema: toTypedSchema(formSchema)
})
Field Mapping Forms
Specialized forms for mapping data fields to chart properties.
Field mapping form pattern for chart configuration
Components:
FieldMappingSelector- Field selection with type detectionDataMappingEditor- Complete data mapping configurationColumnSelector- Column selection from data sources
Features:
- Auto-detection: Automatic field type detection
- Validation: Field compatibility validation
- Preview: Real-time mapping preview
- Suggestions: Smart field mapping suggestions
Layout Patterns
Consistent layout patterns for different page types.
Sidebar Layout
Main application layout with navigation sidebar
Components:
Sidebar- Main navigation with workspace contextSidebarHeader- Logo and global controlsSidebarContent- Navigation menu and workspace selectorSidebarMenu- Primary navigation items
Features:
- Context Switching: Workspace and environment selection
- Responsive Design: Collapsible sidebar for mobile
- Theme Toggle: Light/dark mode switching
- Route Highlighting: Active route indication
Page Layout
Standard page layout pattern for consistent spacing and structure.
Standard page layout structure and spacing
Elements:
- Page Header: Title, description, and primary actions
- Content Area: Main page content with consistent spacing
- Action Bars: Secondary actions and filters
- Loading States: Skeleton layouts during data loading
Modal Layout
Consistent modal and overlay patterns.
Modal layout patterns for different dialog types
Types:
- Standard Modals: Basic dialog interfaces
- Full-screen Modals: Complex configuration interfaces
- Slide-out Panels: Secondary information displays
- Confirmation Dialogs: Simple confirmation interfaces
State Patterns
Patterns for managing component state and reactivity.
Composable State
How components integrate with composable state
Pattern:
// Component using composable state
const {
items,
loading,
error,
fetchItems,
createItem,
updateItem,
deleteItem
} = useMetrics()
// Reactive state automatically updates component
watchEffect(() => {
if (selectedWorkspace.value) {
fetchItems(selectedWorkspace.value.id)
}
})
Local State Management
Local component state management patterns
Guidelines:
- Reactive Refs: Use
ref()for primitive values - Reactive Objects: Use
reactive()for complex objects - Computed Properties: Derive state with
computed() - Watchers: Handle side effects with
watch()andwatchEffect()
Error Handling Patterns
Consistent error handling and user feedback patterns.
Error Display
Error handling and user feedback patterns
Error Types:
- Validation Errors: Form field validation feedback
- API Errors: Network and server error handling
- Component Errors: Component-level error boundaries
- Loading Errors: Failed data loading scenarios
Display Patterns:
- Inline Errors: Field-level validation errors
- Toast Notifications: Global success/error messages
- Error States: Component error state displays
- Retry Mechanisms: User-initiated error recovery
Best Practices
Component Design
- Single Responsibility: Each component should have one clear purpose
- Props Interface: Use TypeScript interfaces for all props
- Event Emission: Emit events for parent component communication
- Slot Utilization: Provide slots for flexible content injection
- Accessibility: Include ARIA labels and keyboard navigation
Performance Optimization
- Lazy Loading: Load components only when needed
- Computed Caching: Use computed properties for expensive operations
- Event Debouncing: Debounce user input for API calls
- Memory Management: Clean up watchers and event listeners
- Bundle Splitting: Split large components for better loading
Reusability
- Generic Interfaces: Design components for reuse across contexts
- Configuration Props: Provide props for customization
- Composable Logic: Extract business logic to composables
- Style Variants: Support different visual styles via props
- Extension Points: Provide hooks for extending functionality
Next Steps
- API Integration - Learn API integration patterns
- UI Components - Explore Studio's custom component library
- Data Flow - Understand data flow patterns
These component patterns provide the foundation for building consistent, maintainable analytics interfaces that scale with your application needs.