What Are States?
States represent the different conditions a component can exist in at any given moment. They determine how a component appears and behaves in response to user interactions, system events, or data changes.Core Component States
All interactive components in our design system should account for these fundamental states:State | Description |
---|---|
Default | The initial appearance of a component before any interaction. This state establishes the component’s baseline visual identity while indicating its purpose and functionality. |
Hover | Appears when a cursor moves over an interactive element, providing a visual cue that the element can be interacted with. |
Active | Occurs when a button or control is being interacted with (pressed, clicked, tapped). This brief state provides immediate feedback that the system has recognized the user’s action. |
Focus | Activated by keyboard navigation or programmatic focus. Focus states must include a 2px focus indicator with a 3:1 contrast ratio to ensure accessibility for keyboard users and those using assistive technologies. |
Disabled | Indicates when an element exists but is unavailable for interaction. Disabled states should maintain the component’s visual structure while clearly communicating its unavailability. |
Error | Used to highlight invalid inputs or system errors. Error states must include both visual indicators and clear messaging with at least a 4:1 contrast ratio to meet accessibility standards. |
Additional Component States
Depending on the component’s complexity, these additional states may apply:State | Description |
---|---|
Loading | Indicates when a component is retrieving data or processing information. Loading states provide essential feedback that prevents user confusion during wait times. |
Expanded/Collapsed | Used for components that can reveal or hide content, such as accordions, dropdowns, or expandable panels. |
Selected | Indicates when an item within a collection has been chosen, such as items in a list, tabs, or menu options. |
Indeterminate | Represents a state between checked and unchecked, primarily used in checkboxes when some (but not all) nested options are selected. |
Understanding Statefulness
Statefulness describes how components remember and maintain information about their condition between interactions.Stateful vs. Stateless Components
Stateful Components
Stateful components maintain memory of past interactions, store data that changes over time, and manage their own internal state. Examples include forms, toggles, accordions, and carousels. These components require:- Documentation of all possible states
- Clear rules for transitions between states
- Consideration of data persistence
- Thoughtful implementation of state logic
Stateless Components
Stateless components don’t maintain internal memory, rendering based solely on their input properties. The same input will always produce the same output. Examples include buttons, labels, icons, and dividers. These components benefit from:- Simpler implementation
- More predictable behavior
- Easier testing and maintenance
- Greater reusability
State Management Patterns
State management refers to the approaches used to control, organize, and maintain state in components and applications.Levels of State Management
Component-Level State
State that only affects a single component should be managed within that component. This approach maintains encapsulation and simplifies reasoning about the component’s behavior.Shared State
When multiple components need access to the same state, consider lifting state to a common parent or using a shared state mechanism. This creates a single source of truth and prevents synchronization issues.Application State
For state that affects large portions of the application (such as authentication, themes, or global settings), use centralized state management. This approach provides consistency across the application and simplifies complex state interactions.State Management Approaches
Controlled vs. Uncontrolled Components
Controlled components receive their state from parent components and notify those parents of any requested changes:State Machines
For components with complex state logic, state machines provide a formal way to define states and transitions. They help prevent invalid states and make behavior more predictable.Documenting States
Thorough documentation of states is essential for consistent implementation. For each component in our design system, document:State Inventory Matrix
State | Visual Treatment | Behavior | Accessibility Considerations | Code Examples |
---|---|---|---|---|
Default | [Describe appearance] | [Describe behavior] | [List accessibility features] | [Provide code snippet] |
Hover | Background lightens | Cursor changes to pointer | N/A | :hover selector |
Focus | 2px blue outline | Responds to keyboard | Focus visible | [data-state="focused"] |
Disabled | Gray appearance | No interaction | Communicates disabled status | [data-disabled="true"] |
State Transition Diagram
For complex components, include a diagram showing all possible states and transitions between them. For example, a form submission process might follow this pattern:Implementing States in Design and Code
Design Implementation
When designing components, consider:- Consistent Visual Language: Use consistent visual cues for the same states across different components
- Clear State Communication: Ensure each state is visually distinct and communicates its purpose
- Transition Design: Define how components transition between states, including timing and animation
- Composition: Design states that compose well with other components and in different contexts
Code Implementation
When implementing states in code:- State Naming: Use clear, consistent names for states in class names, data attributes, and variables
- Accessibility: Ensure proper ARIA attributes are applied based on the component’s state
- Performance: Optimize how state changes trigger rendering updates
- Testing: Test all possible state transitions and edge cases
Practical Example: Form Component
Consider a form component with multiple states. Here’s how we might approach its implementation:States Definition
- Idle: Initial state, form is ready for input
- Validating: Checking input validity
- Submitting: Sending data to server
- Success: Submission completed successfully
- Error: Submission failed
Implementation Example
Best Practices
- Minimize State Complexity: Keep state as simple as possible and limit the number of stateful components
- Single Source of Truth: Avoid duplicating state across components
- Predictable Transitions: Make state transitions clear and predictable
- Accessibility First: Ensure states are properly communicated to all users, including those using assistive technologies
- Performance Consideration: Be mindful of how state changes affect rendering performance
- Test All States: Thoroughly test all states and transitions, including edge cases
- Document Everything: Maintain comprehensive documentation of all states and their behaviors