flutter_gen_ai_chat_ui 2.0.2
flutter_gen_ai_chat_ui: ^2.0.2 copied to clipboard
A Flutter package for creating AI chat interfaces with streaming responses, markdown support, and extensive customization.
Flutter Gen AI Chat UI #
A modern, customizable chat UI for AI applications built with Flutter. Features streaming responses, markdown support, and rich customization options.
Development Status: This package is under active development. You may encounter breaking changes with each update as we improve the API and add new features. Please check the CHANGELOG before updating to a new version.
Table of Contents #
![]() Dark Mode |
![]() Chat Demo |
Features #
Core Features #
- π¨ Dark/light mode with adaptive theming
- π« Word-by-word streaming with animations
- π Enhanced markdown support with code highlighting
- π€ Optional speech-to-text integration
- π± Responsive layout with customizable width
- π RTL language support
- β‘ High performance message handling
- π Improved pagination support
AI-Specific Features #
- π Customizable welcome message
- β Example questions component
- π¬ Persistent example questions
- π AI typing indicators
- π Streaming markdown rendering
UI Components #
- π¬ Customizable message bubbles
- β¨οΈ Multiple input field styles (minimal, glassmorphic, custom)
- π Loading indicators with shimmer
- β¬οΈ Smart scroll management
- π¨ Enhanced theme customization
- π Better code block styling
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
flutter_gen_ai_chat_ui: ^2.0.2
Then run:
flutter pub get
β οΈ Important: This package is under active development. We recommend pinning to a specific version in your pubspec.yaml to avoid unexpected breaking changes when you update. Always check the CHANGELOG before upgrading.
Basic Usage #
import 'package:flutter_gen_ai_chat_ui/flutter_gen_ai_chat_ui.dart';
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _controller = ChatMessagesController();
final _currentUser = ChatUser(id: 'user', firstName: 'User');
final _aiUser = ChatUser(id: 'ai', firstName: 'AI Assistant');
bool _isLoading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('AI Chat')),
body: AiChatWidget(
// Required parameters
currentUser: _currentUser,
aiUser: _aiUser,
controller: _controller,
onSendMessage: _handleSendMessage,
// Optional parameters
loadingConfig: LoadingConfig(isLoading: _isLoading),
inputOptions: InputOptions(
hintText: 'Ask me anything...',
sendOnEnter: true,
),
welcomeMessageConfig: WelcomeMessageConfig(
title: 'Welcome to AI Chat',
questionsSectionTitle: 'Try asking me:',
),
exampleQuestions: [
ExampleQuestion(question: "What can you help me with?"),
ExampleQuestion(question: "Tell me about your features"),
],
),
);
}
Future<void> _handleSendMessage(ChatMessage message) async {
setState(() => _isLoading = true);
try {
// Your AI service logic here
await Future.delayed(Duration(seconds: 1)); // Simulating API call
// Add AI response
_controller.addMessage(ChatMessage(
text: "This is a response to: ${message.text}",
user: _aiUser,
createdAt: DateTime.now(),
));
} finally {
setState(() => _isLoading = false);
}
}
}
Configuration Options #
AiChatWidget Parameters #
Required Parameters
AiChatWidget(
// Required parameters
currentUser: ChatUser(...), // The current user
aiUser: ChatUser(...), // The AI assistant
controller: ChatMessagesController(), // Message controller
onSendMessage: (message) { // Message handler
// Handle user messages here
},
// ... optional parameters
)
Optional Parameters
AiChatWidget(
// ... required parameters
// Message display options
messages: [], // Optional list of messages (if not using controller)
messageOptions: MessageOptions(...), // Message bubble styling
messageListOptions: MessageListOptions(...), // Message list behavior
// Input field customization
inputOptions: InputOptions(...), // Input field styling and behavior
readOnly: false, // Whether the chat is read-only
// AI-specific features
exampleQuestions: [ // Suggested questions for users
ExampleQuestion(question: 'What is AI?'),
],
persistentExampleQuestions: true, // Keep questions visible after welcome
enableAnimation: true, // Enable message animations
enableMarkdownStreaming: true, // Enable streaming text
streamingDuration: Duration(milliseconds: 30), // Stream speed
welcomeMessageConfig: WelcomeMessageConfig(...), // Welcome message styling
// Loading states
loadingConfig: LoadingConfig( // Loading configuration
isLoading: false,
showCenteredIndicator: true,
),
// Pagination
paginationConfig: PaginationConfig( // Pagination configuration
enabled: true,
reverseOrder: true, // Newest messages at bottom
),
// Layout
maxWidth: 800, // Maximum width
padding: EdgeInsets.all(16), // Overall padding
)
Input Field Customization #
The package offers multiple ways to style the input field:
Default Input
InputOptions(
// Basic properties
sendOnEnter: true,
// Styling
textStyle: TextStyle(...),
decoration: InputDecoration(...),
)
Minimal Input
InputOptions.minimal(
hintText: 'Ask a question...',
textColor: Colors.black,
hintColor: Colors.grey,
backgroundColor: Colors.white,
borderRadius: 24.0,
)
Glassmorphic (Frosted Glass) Input
InputOptions.glassmorphic(
colors: [Colors.blue.withOpacity(0.2), Colors.purple.withOpacity(0.2)],
borderRadius: 24.0,
blurStrength: 10.0,
hintText: 'Ask me anything...',
textColor: Colors.white,
)
Custom Input
InputOptions.custom(
decoration: yourCustomDecoration,
textStyle: yourCustomTextStyle,
sendButtonBuilder: (onSend) => CustomSendButton(onSend: onSend),
)
Always-Visible Send Button Without Focus Issues (version 2.0.2+)
The send button is now hardcoded to always be visible by design, regardless of text content. This removes the need for an explicit setting and ensures a consistent experience across the package.
By default:
- The send button is always shown regardless of text input
- Focus is maintained when tapping outside the input field
- The keyboard's send button is disabled by default to prevent focus issues
// Configure input options to ensure a consistent typing experience
InputOptions(
// Prevent losing focus when tapping outside
unfocusOnTapOutside: false,
// Use newline for Enter key to prevent keyboard focus issues
textInputAction: TextInputAction.newline,
)
Message Bubble Customization #
MessageOptions(
// Basic options
showTime: true,
showUserName: true,
// Styling
bubbleStyle: BubbleStyle(
userBubbleColor: Colors.blue.withOpacity(0.1),
aiBubbleColor: Colors.white,
userNameColor: Colors.blue.shade700,
aiNameColor: Colors.purple.shade700,
bottomLeftRadius: 22,
bottomRightRadius: 22,
enableShadow: true,
),
)
Loading Configuration #
LoadingConfig(
isLoading: true, // Whether the AI is currently generating a response
loadingIndicator: CustomLoadingWidget(), // Custom loading indicator
typingIndicatorColor: Colors.blue, // Color for the typing indicator
showCenteredIndicator: false, // Show indicator in center or as typing
)
Pagination Configuration #
PaginationConfig(
enabled: true, // Enable pagination for large message histories
loadingIndicatorOffset: 100, // How far from top to trigger loading
reverseOrder: true, // Show newest messages at bottom
)
Advanced Features #
Streaming Text #
To enable word-by-word text streaming:
AiChatWidget(
// ... other parameters
enableMarkdownStreaming: true,
streamingDuration: Duration(milliseconds: 30),
onSendMessage: (message) async {
// Start with an empty message
final aiMessage = ChatMessage(
text: "",
user: aiUser,
createdAt: DateTime.now(),
isMarkdown: true,
);
// Add to the chat
_chatController.addMessage(aiMessage);
// Stream the response word by word
final response = "This is a **streaming** response with `code` and more...";
String accumulating = "";
for (final word in response.split(" ")) {
await Future.delayed(Duration(milliseconds: 100));
accumulating += (accumulating.isEmpty ? "" : " ") + word;
// Update the message with new text
_chatController.updateMessage(
aiMessage.copyWith(text: accumulating),
);
}
},
)
Welcome Message Configuration #
// The welcome message is disabled by default and only appears
// when this configuration is provided
WelcomeMessageConfig(
title: "Welcome to My AI Assistant",
containerPadding: EdgeInsets.all(24),
questionsSectionTitle: "Try asking me:",
)
Controller Methods #
// Initialize controller
final controller = ChatMessagesController();
// Add a message
controller.addMessage(ChatMessage(...));
// Add multiple messages
controller.addMessages([ChatMessage(...), ChatMessage(...)]);
// Update a message (useful for streaming)
controller.updateMessage(message.copyWith(text: newText));
// Clear all messages
controller.clearMessages();
// Hide the welcome message
controller.hideWelcomeMessage();
// Show/hide welcome message programmatically
controller.showWelcomeMessage = true; // Show welcome message
controller.showWelcomeMessage = false; // Hide welcome message
// Manually scroll to bottom
controller.scrollToBottom();
// Load more messages (for pagination)
controller.loadMore(() async {
return await fetchOlderMessages();
});
Platform Support #
β Android β iOS β Web β macOS β Windows β Linux
Examples #
Check the example directory for complete sample applications showcasing different features.
Development & Contributing #
We welcome contributions to improve the Flutter Gen AI Chat UI package!
Before submitting a pull request:
- Ensure your code follows the project style guidelines
- Add tests for any new features
- Update documentation as needed
For maintainers releasing new versions, please refer to our release checklist to ensure all necessary steps are completed before publishing.
License #
MIT License
β If you find this package helpful, please star the repository!