Appearance
State Enums System
Overview
The state enums system provides type-safe state management for UI components. States are defined as TypeScript enums with string values, enabling both compile-time type checking and runtime validation. The system follows the same pattern as the Templates System.
Architecture
1. State Definition (types.ts)
States are defined as enums with lowercase string values:
typescript
/**
* Submit Button States
* Used for form submit button state management
* Enum values serve as both display labels and type-safe identifiers
*/
export enum SubmitButtonState {
DEFAULT = 'default',
HOVER = 'hover',
DISABLED = 'disabled',
LOADING = 'loading',
SUCCESS = 'success',
ERROR = 'error',
}
/**
* Input Field States
* Used for form input field state management
* Enum values serve as both display labels and type-safe identifiers
*/
export enum InputFieldState {
DEFAULT = 'default',
HOVER = 'hover',
FOCUS = 'focus',
}2. State Helpers (stateHelpers.ts)
Helper functions provide easy access to state arrays and type guards:
typescript
/**
* Get all submit button states as an array
* @returns ['default', 'hover', 'disabled', 'loading', 'success', 'error']
*/
export const getSubmitButtonStates = (): string[] => {
return Object.values(SubmitButtonState)
}
/**
* Get all input field states as an array
* @returns ['default', 'hover', 'focus']
*/
export const getInputFieldStates = (): string[] => {
return Object.values(InputFieldState)
}
/**
* Type guard to check if a value is a valid SubmitButtonState
*/
export const isSubmitButtonState = (value: string): value is SubmitButtonState => {
return Object.values(SubmitButtonState).includes(value as SubmitButtonState)
}
/**
* Type guard to check if a value is a valid InputFieldState
*/
export const isInputFieldState = (value: string): value is InputFieldState => {
return Object.values(InputFieldState).includes(value as InputFieldState)
}Usage in Components
StateConfigurationCard
The StateConfigurationCard component uses state enums to provide type-safe state management:
vue
<template>
<StateConfigurationCard
title="Button States"
:current-state="blockData.submitState"
:states="submitButtonStates"
@update:state="updateValue($event, 'submitState')"
@update:is-state-preview="updateValue($event, 'isStatePreview')"
>
<template #default-sections>
<!-- Default state configuration -->
</template>
<template #hover-sections>
<!-- Hover state configuration -->
</template>
<template #disabled-sections>
<!-- Disabled state configuration -->
</template>
<!-- ... more state-specific slots -->
</StateConfigurationCard>
</template>
<script>
import { getSubmitButtonStates } from '@/pages/Chatbots/components/BuilderVisuals/Blocks/data/stateHelpers'
export default {
data() {
return {
submitButtonStates: getSubmitButtonStates(),
}
},
}
</script>Type-Safe State Access
typescript
import { SubmitButtonState, InputFieldState } from '@/pages/Chatbots/components/BuilderVisuals/Blocks/data/types'
// Use enum keys for type safety
const currentState = SubmitButtonState.HOVER // 'hover'
// Use enum values for comparisons
if (blockData.submitState === SubmitButtonState.LOADING) {
// Show loading indicator
}
// Get all states as array
const allStates = getSubmitButtonStates()
// ['default', 'hover', 'disabled', 'loading', 'success', 'error']Benefits
1. Type Safety
typescript
// ✅ Type-safe - IDE autocomplete works
const state: SubmitButtonState = SubmitButtonState.HOVER
// ❌ Compile error - typo caught at build time
const state: SubmitButtonState = SubmitButtonState.HOVR2. Single Source of Truth
typescript
// States defined once in types.ts
export enum SubmitButtonState {
DEFAULT = 'default',
HOVER = 'hover',
// ... add new states here
}
// Automatically available everywhere via helper
const states = getSubmitButtonStates()3. Refactoring Safety
When renaming or adding states:
- Update the enum in
types.ts - TypeScript compiler finds all usages
- No hardcoded strings to hunt down
4. Runtime Validation
typescript
// Validate user input or API responses
if (isSubmitButtonState(userInput)) {
// Safe to use as SubmitButtonState
applyState(userInput)
}Comparison with Templates System
Both systems follow the same pattern:
| Feature | Templates | States |
|---|---|---|
| Definition | FormTemplate enum | SubmitButtonState / InputFieldState enums |
| Helper | getFormTemplate() | getSubmitButtonStates() / getInputFieldStates() |
| Type Guard | N/A | isSubmitButtonState() / isInputFieldState() |
| Usage | Template selection | State management in configuration |
Adding New States
1. Define the Enum
typescript
// types.ts
export enum CustomComponentState {
DEFAULT = 'default',
ACTIVE = 'active',
INACTIVE = 'inactive',
}2. Create Helper Functions
typescript
// stateHelpers.ts
export const getCustomComponentStates = (): string[] => {
return Object.values(CustomComponentState)
}
export const isCustomComponentState = (value: string): value is CustomComponentState => {
return Object.values(CustomComponentState).includes(value as CustomComponentState)
}3. Use in Component
vue
<script>
import { getCustomComponentStates } from '@/path/to/stateHelpers'
export default {
data() {
return {
customStates: getCustomComponentStates(),
}
},
}
</script>Best Practices
- Always use enums instead of hardcoded strings for state values
- Use helper functions to get state arrays dynamically
- Use type guards when validating external input
- Document state purposes in enum comments
- Keep state names lowercase for consistency with CSS classes
Related Documentation
- Templates System - Similar pattern for template management
- StateConfigurationCard - Component that uses state enums
- FormConfiguration - Example usage