expansion_card 1.0.1
expansion_card: ^1.0.1 copied to clipboard
A customizable Flutter expansion card with optional animated image backgrounds.
example/lib/main.dart
import 'package:expansion_card/expansion_card.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Expansion Card Example',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF2AA7A5),
brightness: Brightness.dark,
),
scaffoldBackgroundColor: const Color(0xFF09131B),
appBarTheme: const AppBarTheme(
backgroundColor: Colors.transparent,
elevation: 0,
scrolledUnderElevation: 0,
),
),
home: const ExampleHomePage(),
);
}
}
class ExampleHomePage extends StatelessWidget {
const ExampleHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Expansion Card')),
body: Stack(
children: <Widget>[
const _Backdrop(),
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 540),
child: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20),
children: const <Widget>[
_CardShell(
child: ExpansionCard(
backgroundColor: Color(0xFF132733),
expansionArrowColor: Colors.white,
color: Color(0xFF78E3DE),
initiallyExpanded: true,
topMargin: 24,
leading: _CircleBadge(
icon: Icons.auto_awesome_rounded,
color: Color(0xFF78E3DE),
),
title: _CardTitle(
title: 'Experience',
subtitle: 'Tap to collapse',
),
children: <Widget>[
_FeatureTile(
title: 'Cleaner layout',
description:
'Only the cards are visible so the widget becomes the focus.',
),
_FeatureTile(
title: 'Better presentation',
description:
'Rounded surfaces, softer contrast, and spacing that feels calmer.',
),
SizedBox(height: 8),
],
),
),
SizedBox(height: 18),
_CardShell(
child: ExpansionCard(
backgroundColor: Color(0xFF1B1E3D),
expansionArrowColor: Color(0xFFFFD36E),
color: Color(0xFFFFD36E),
topMargin: 24,
leading: _CircleBadge(
icon: Icons.bolt_rounded,
color: Color(0xFFFFD36E),
),
title: _CardTitle(
title: 'Highlights',
subtitle: 'Compact variation',
),
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(16, 8, 16, 20),
child: Wrap(
spacing: 10,
runSpacing: 10,
children: <Widget>[
_InfoChip(label: 'Dart 3'),
_InfoChip(label: 'Flutter'),
_InfoChip(label: 'Null safe'),
_InfoChip(label: 'Simple API'),
],
),
),
],
),
),
],
),
),
),
],
),
);
}
}
class _Backdrop extends StatelessWidget {
const _Backdrop();
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[Color(0xFF0B1821), Color(0xFF09131B)],
),
),
child: Stack(
children: <Widget>[
Positioned(
top: 120,
left: -60,
child: _BlurOrb(size: 180, color: Color(0xFF2AA7A5)),
),
Positioned(
bottom: 120,
right: -40,
child: _BlurOrb(size: 160, color: Color(0xFF7C56FF)),
),
],
),
);
}
}
class _BlurOrb extends StatelessWidget {
const _BlurOrb({required this.size, required this.color});
final double size;
final Color color;
@override
Widget build(BuildContext context) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: <Color>[
color.withValues(alpha: 0.24),
color.withValues(alpha: 0),
],
),
),
);
}
}
class _CardShell extends StatelessWidget {
const _CardShell({required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
border: Border.all(color: Colors.white.withValues(alpha: 0.08)),
boxShadow: const <BoxShadow>[
BoxShadow(
color: Color(0x30000000),
blurRadius: 28,
offset: Offset(0, 16),
),
],
),
child: ClipRRect(borderRadius: BorderRadius.circular(30), child: child),
);
}
}
class _CircleBadge extends StatelessWidget {
const _CircleBadge({required this.icon, required this.color});
final IconData icon;
final Color color;
@override
Widget build(BuildContext context) {
return Container(
width: 44,
height: 44,
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
child: Icon(icon, color: const Color(0xFF09131B)),
);
}
}
class _CardTitle extends StatelessWidget {
const _CardTitle({required this.title, required this.subtitle});
final String title;
final String subtitle;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w800,
color: Colors.white,
letterSpacing: -0.8,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: const TextStyle(fontSize: 15, color: Color(0xFFB2C7CF)),
),
],
);
}
}
class _FeatureTile extends StatelessWidget {
const _FeatureTile({required this.title, required this.description});
final String title;
final String description;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 4),
Text(
description,
style: const TextStyle(
color: Color(0xFFB6CBD3),
fontSize: 14,
height: 1.45,
),
),
],
),
);
}
}
class _InfoChip extends StatelessWidget {
const _InfoChip({required this.label});
final String label;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(999),
),
child: Text(
label,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
),
),
);
}
}