Skip to content

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.HOVR

2. 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:

  1. Update the enum in types.ts
  2. TypeScript compiler finds all usages
  3. 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:

FeatureTemplatesStates
DefinitionFormTemplate enumSubmitButtonState / InputFieldState enums
HelpergetFormTemplate()getSubmitButtonStates() / getInputFieldStates()
Type GuardN/AisSubmitButtonState() / isInputFieldState()
UsageTemplate selectionState 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

  1. Always use enums instead of hardcoded strings for state values
  2. Use helper functions to get state arrays dynamically
  3. Use type guards when validating external input
  4. Document state purposes in enum comments
  5. Keep state names lowercase for consistency with CSS classes

Internal documentation