leetcode_heatmap 0.1.1
leetcode_heatmap: ^0.1.1 copied to clipboard
A Flutter widget to display a GitHub-style heatmap of LeetCode submissions using the LeetCode GraphQL API.
LeetCode Heatmap Widget #
A highly customizable Flutter widget that displays a GitHub-style heatmap for LeetCode submission activity. Perfect for tracking coding progress and displaying achievements in your Flutter apps.

Features #
- GitHub-style heatmap visualization
- Highly customizable appearance and behavior
- Responsive design with horizontal scrolling
- Custom color schemes and gradients
- Month and day labels (optional)
- Interactive tooltips with submission counts
- Statistics display (total submissions, streaks)
- Smooth animations and transitions
- Auto-scroll to current period
- Extensive customization options
Getting Started #
Prerequisites #
- Flutter SDK
- LeetCode API integration (you'll need to implement
LeetCodeApiandLeetCodeDataclasses)
Installation #
-
Add the widget files to your Flutter project:
lib/ ├── widgets/ │ └── leetcode_heatmap.dart ├── api/ │ └── leetcode_api.dart └── models/ └── leetcode_data.dart -
Import the widget in your Dart file:
import 'package:your_app/widgets/leetcode_heatmap.dart';
📖 Basic Usage #
Simple Implementation #
LeetCodeHeatmap(
username: 'your-leetcode-username',
)
With Custom Year #
LeetCodeHeatmap(
username: 'your-leetcode-username',
year: 2024,
)
🎨 Customization Options #
Cell Styling #
LeetCodeHeatmap(
username: 'your-username',
cellSize: 15.0, // Size of each cell
cellSpacing: 2.0, // Spacing between cells
cellBorderRadius: BorderRadius.circular(4), // Cell border radius
colors: [ // Custom color scheme
Color(0xFFEBEDF0), // No activity
Color(0xFF9BE9A8), // Low activity
Color(0xFF40C463), // Medium activity
Color(0xFF30A14E), // High activity
Color(0xFF216E39), // Very high activity
],
futureCellColor: Colors.grey[200]!, // Color for future dates
showBorder: true, // Add borders to cells
borderColor: Colors.grey[300]!, // Border color
borderWidth: 1.0, // Border width
)
Text Styling #
LeetCodeHeatmap(
username: 'your-username',
statsTextStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
legendTextStyle: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
headerTextStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
tooltipTextStyle: TextStyle(
fontSize: 12,
color: Colors.white,
),
)
Layout Options #
LeetCodeHeatmap(
username: 'your-username',
padding: EdgeInsets.all(16.0), // Widget padding
weekSpacing: 3.0, // Spacing between weeks
showScrollbar: true, // Show/hide scrollbar
autoScrollToEnd: true, // Auto-scroll to current date
showMonthLabels: true, // Show month headers
showDayLabels: true, // Show day labels (Sun, Mon, etc.)
)
Feature Toggles #
LeetCodeHeatmap(
username: 'your-username',
showStats: true, // Show statistics
showLegend: true, // Show color legend
showTooltips: true, // Show hover tooltips
showMonthLabels: true, // Show month labels
showDayLabels: false, // Show day-of-week labels
showBorder: false, // Show cell borders
)
Custom Formatters #
LeetCodeHeatmap(
username: 'your-username',
tooltipFormatter: (count, date) {
return 'Solved $count problems on ${date.day}/${date.month}/${date.year}';
},
statsFormatter: (totalDays, year) {
return '$totalDays coding sessions in $year';
},
streakFormatter: (streak) {
return '🔥 $streak day streak!';
},
)
Animation Settings #
LeetCodeHeatmap(
username: 'your-username',
enableAnimation: true, // Enable fade-in animation
animationDuration: Duration(milliseconds: 500),
animationCurve: Curves.easeInOut,
)
Custom Loading & Error States #
LeetCodeHeatmap(
username: 'your-username',
loadingWidget: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
),
errorWidgetBuilder: (error) {
return Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Icon(Icons.error, color: Colors.red, size: 48),
SizedBox(height: 8),
Text('Failed to load data: $error'),
ElevatedButton(
onPressed: () => _refreshHeatmap(),
child: Text('Retry'),
),
],
),
);
},
)
🎨 Pre-built Themes #
GitHub Theme #
LeetCodeHeatmap(
username: 'your-username',
colors: [
Color(0xFFEBEDF0),
Color(0xFF9BE9A8),
Color(0xFF40C463),
Color(0xFF30A14E),
Color(0xFF216E39),
],
cellSize: 12.0,
cellSpacing: 1.0,
)
Dark Theme #
LeetCodeHeatmap(
username: 'your-username',
colors: [
Color(0xFF161B22),
Color(0xFF0E4429),
Color(0xFF006D32),
Color(0xFF26A641),
Color(0xFF39D353),
],
backgroundColor: Color(0xFF0D1117),
cellSize: 12.0,
cellSpacing: 1.0,
statsTextStyle: TextStyle(color: Colors.white),
legendTextStyle: TextStyle(color: Colors.white70),
)
Vibrant Theme #
LeetCodeHeatmap(
username: 'your-username',
colors: [
Colors.grey[100]!,
Colors.blue[200]!,
Colors.blue[400]!,
Colors.blue[600]!,
Colors.blue[800]!,
],
cellSize: 14.0,
cellSpacing: 2.0,
cellBorderRadius: BorderRadius.circular(4),
showBorder: true,
borderColor: Colors.blue[100]!,
)
🔧 Required Dependencies #
You'll need to implement these classes for the widget to work:
LeetCodeApi Class #
class LeetCodeApi {
static Future<LeetCodeData> fetchUserCalendar(
String username, {
int? year,
}) async {
// Your API implementation here
// Return LeetCodeData object
}
}
LeetCodeData Model #
class LeetCodeData {
final int totalActiveDays;
final int streak;
final Map<dynamic, dynamic> submissionCalendar;
LeetCodeData({
required this.totalActiveDays,
required this.streak,
required this.submissionCalendar,
});
}
📱 Responsive Design #
The widget automatically adapts to different screen sizes:
// For mobile devices
LeetCodeHeatmap(
username: 'your-username',
cellSize: 10.0,
showDayLabels: false,
showMonthLabels: true,
)
// For tablets/desktop
LeetCodeHeatmap(
username: 'your-username',
cellSize: 14.0,
showDayLabels: true,
showMonthLabels: true,
weekSpacing: 3.0,
)
🔄 Refresh Functionality #
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final GlobalKey<_LeetCodeHeatmapState> _heatmapKey = GlobalKey();
void _refreshHeatmap() {
_heatmapKey.currentState?.refresh();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
LeetCodeHeatmap(
key: _heatmapKey,
username: 'your-username',
),
ElevatedButton(
onPressed: _refreshHeatmap,
child: Text('Refresh'),
),
],
);
}
}
🎯 Complete Example #
import 'package:flutter/material.dart';
import 'package:your_app/widgets/leetcode_heatmap.dart';
class LeetCodeProfilePage extends StatelessWidget {
final String username;
const LeetCodeProfilePage({
Key? key,
required this.username,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('$username\'s LeetCode Activity'),
backgroundColor: Colors.green[700],
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Coding Activity',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
LeetCodeHeatmap(
username: username,
cellSize: 14.0,
cellSpacing: 2.0,
showMonthLabels: true,
showDayLabels: true,
colors: [
Colors.grey[100]!,
Colors.green[200]!,
Colors.green[400]!,
Colors.green[600]!,
Colors.green[800]!,
],
statsTextStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
tooltipFormatter: (count, date) {
if (count == 0) return 'No submissions on ${date.day}/${date.month}';
return '$count problem${count > 1 ? 's' : ''} solved on ${date.day}/${date.month}/${date.year}';
},
),
],
),
),
),
);
}
}
🐛 Troubleshooting #
Common Issues #
- ScrollController Error: Make sure you're not reusing scroll controllers
- API Connection: Verify your LeetCode API implementation
- Data Format: Ensure submission calendar data is in the correct format
- Performance: For large datasets, consider implementing data pagination
Performance Tips #
- Use appropriate
cellSizefor your screen size - Implement data caching in your API layer
- Consider using
enableAnimation: falsefor better performance on older devices
📄 License #
This widget is open source and available under the MIT License.
🤝 Contributing #
Contributions are welcome! Please feel free to submit issues and pull requests.
📞 Support #
If you encounter any issues or have questions, please create an issue in the repository.
Happy Coding! 🚀