Custom Styling and State Classes
Overview
The Wabee Chat widget provides CSS state classes that allow you to customize the appearance based on the current chat state. These classes are applied directly to the Layout component and can be used to create custom loading animations, status indicators, and visual feedback.
Setup
To enable state classes, set enableStateClasses: true
in your widget initialization:
window.WabeeChat.init({
target: '#wabee-chat-container',
apiKey: 'your_api_key_here',
agentUrl: 'https://your-agent.wabee.ai/core/v1',
sseUrl: 'https://notifications-hub.wabee.ai/events',
enableStateClasses: true, // Required for state classes
showStatusText: true // Optional: show/hide status text
});
Available State Classes
State Classes (applied to Layout element)
.wabee-chat-idle
- No activity.wabee-chat-processing
- Processing user input.wabee-chat-generating
- AI generating response.wabee-chat-streaming
- AI typing text output.wabee-chat-loading
- Chat loading.wabee-chat-session-loading
- Session loading
Internal Element Classes
.wabee-loading-container
- Container for loading elements.wabee-loading-indicator
- Pulsing status indicator.wabee-loading-status-text
- Status text element.wabee-loading-spinner
- Spinner element.wabee-input-loading-container
- Input loading container.wabee-input-loading-spinner
- Input spinner.wabee-input-stop-button
- Stop button.wabee-conversation-loading
- Conversation loading.wabee-conversation-loading-icon
- Conversation loading icon
Custom Loading Animations
Status Bar Implementation
The state classes are applied directly to the chat layout element, so target them directly:
/* Add position relative to all state classes */
.wabee-chat-idle,
.wabee-chat-processing,
.wabee-chat-generating,
.wabee-chat-streaming,
.wabee-chat-loading,
.wabee-chat-session-loading {
position: relative;
}
/* Create a status bar at the top */
.wabee-chat-idle::before,
.wabee-chat-processing::before,
.wabee-chat-generating::before,
.wabee-chat-streaming::before,
.wabee-chat-loading::before,
.wabee-chat-session-loading::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
z-index: 1000;
}
/* State-specific colors */
.wabee-chat-idle::before {
background-color: #C5E85C;
}
.wabee-chat-processing::before {
background-color: #ffc107;
animation: progress-bar 2s infinite;
}
.wabee-chat-generating::before {
background-color: #6f42c1;
animation: progress-bar 1.5s infinite;
}
.wabee-chat-streaming::before {
background-color: #dc3545;
animation: streaming-bar 1s infinite;
}
.wabee-chat-loading::before,
.wabee-chat-session-loading::before {
background-color: #6c757d;
animation: loading-bar 1.5s infinite;
}
/* Animations */
@keyframes progress-bar {
0% { transform: scaleX(0); }
50% { transform: scaleX(0.8); }
100% { transform: scaleX(1); }
}
@keyframes streaming-bar {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
@keyframes loading-bar {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
Customizing Internal Elements
You can also style the internal loading elements within different states:
/* Style the loading indicator during generating state */
.wabee-chat-generating .wabee-loading-indicator {
background: #6f42c1 !important;
box-shadow: 0 0 12px rgba(111, 66, 193, 0.5) !important;
}
/* Style the loading indicator during streaming state */
.wabee-chat-streaming .wabee-loading-indicator {
background: #dc3545 !important;
box-shadow: 0 0 12px rgba(220, 53, 69, 0.5) !important;
}
/* Style other loading elements */
.wabee-chat-processing .wabee-loading-spinner {
color: #ffc107;
}
Complete Implementation Example
Here's a working example based on the examples above:
<!DOCTYPE html>
<html>
<head>
<style>
/* State classes are applied directly to the Layout component */
.wabee-chat-idle,
.wabee-chat-processing,
.wabee-chat-generating,
.wabee-chat-streaming,
.wabee-chat-loading,
.wabee-chat-session-loading {
position: relative;
}
/* Status bar implementation */
.wabee-chat-idle::before,
.wabee-chat-processing::before,
.wabee-chat-generating::before,
.wabee-chat-streaming::before,
.wabee-chat-loading::before,
.wabee-chat-session-loading::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
z-index: 1000;
}
/* State-specific colors */
.wabee-chat-idle::before { background-color: #C5E85C; }
.wabee-chat-processing::before {
background-color: #ffc107;
animation: progress-bar 2s infinite;
}
.wabee-chat-generating::before {
background-color: #6f42c1;
animation: progress-bar 1.5s infinite;
}
.wabee-chat-streaming::before {
background-color: #dc3545;
animation: streaming-bar 1s infinite;
}
.wabee-chat-loading::before,
.wabee-chat-session-loading::before {
background-color: #6c757d;
animation: loading-bar 1.5s infinite;
}
/* Internal element styling */
.wabee-chat-generating .wabee-loading-indicator {
background: #6f42c1 !important;
box-shadow: 0 0 12px rgba(111, 66, 193, 0.5) !important;
}
/* Animations */
@keyframes progress-bar {
0% { transform: scaleX(0); }
50% { transform: scaleX(0.8); }
100% { transform: scaleX(1); }
}
@keyframes streaming-bar {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
@keyframes loading-bar {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
</style>
</head>
<body>
<div id="wabee-chat-container"></div>
<script src="https://platform.wabee.ai/scripts/wabee-chat-browser.umd_v1_2_25.js"></script>
<script>
window.WabeeChat.init({
target: '#wabee-chat-container',
apiKey: 'your_api_key_here',
agentUrl: 'https://your-agent.wabee.ai/core/v1',
sseUrl: 'https://notifications-hub.wabee.ai/events',
width: '100%',
height: '100%',
enableStateClasses: true, // Required for state classes
showStatusText: true // Optional: show/hide status text
});
</script>
</body>
</html>
Best Practices
Performance Considerations
- Use CSS Transitions: Smooth state changes with CSS transitions instead of JavaScript
- Limit Animation Complexity: Keep animations lightweight to avoid performance issues
- Test on Mobile: Ensure state indicators work well on touch devices
Accessibility
- Color Contrast: Ensure sufficient color contrast for all state indicators
- Screen Reader Support: Use
aria-label
attributes for visual-only indicators - Reduced Motion: Respect
prefers-reduced-motion
for users who prefer minimal animations
@media (prefers-reduced-motion: reduce) {
.wabee-chat-streaming::before,
.wabee-chat-processing::before,
.wabee-chat-generating::before {
animation: none;
}
}
Browser Compatibility
- State classes work in all modern browsers
- CSS animations are supported in IE10+
- For older browsers, provide fallback styling without animations
Troubleshooting
Common Issues
- State classes not working: Ensure
enableStateClasses: true
is set in initialization - CSS not applying: State classes are applied to the Layout component, not a container div
- Animations not showing: Check browser console for state class changes to verify they're being applied
Debugging State Changes
Use browser developer tools to inspect the chat container and verify which state classes are being applied:
// Monitor state class changes in browser console
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
console.log('State classes changed:', mutation.target.className);
}
});
});
// Find the Layout element (it will have ant-layout class)
const layoutElement = document.querySelector('.ant-layout');
if (layoutElement) {
observer.observe(layoutElement, { attributes: true });
}
State Lifecycle
The typical state flow is:
1. idle
→ User starts typing
2. processing
→ User submits message
3. generating
→ AI processes and prepares response
4. streaming
→ AI outputs text tokens
5. idle
→ Response complete
Multiple states can be active simultaneously (e.g., generating
+ loading
).
Advanced Examples
Custom State Indicators
/* Add visual feedback for each state */
.wabee-chat-idle {
border-left: 4px solid #C5E85C;
}
.wabee-chat-processing {
border-left: 4px solid #ffc107;
}
.wabee-chat-generating {
border-left: 4px solid #6f42c1;
}
.wabee-chat-streaming {
border-left: 4px solid #dc3545;
}
State-Specific Styling
/* Change background during different states */
.wabee-chat-processing {
background-color: rgba(255, 193, 7, 0.05);
}
.wabee-chat-generating {
background-color: rgba(111, 66, 193, 0.05);
}
.wabee-chat-streaming {
background-color: rgba(220, 53, 69, 0.05);
}
Multiple Element Targeting
/* Style multiple internal elements */
.wabee-chat-generating .wabee-loading-indicator,
.wabee-chat-generating .wabee-loading-spinner {
color: #6f42c1;
}
.wabee-chat-streaming .wabee-loading-status-text {
color: #dc3545;
font-weight: bold;
}
Next Steps
- Explore embedding chat widget for basic setup
- Learn about request interceptors for dynamic configuration
- Review the API documentation for advanced integration options