common_designs 1.0.0
common_designs: ^1.0.0 copied to clipboard
A comprehensive, production-grade design system with robust animations for Flutter apps. Inspired by modern e-commerce interfaces with smooth transitions, interactive animations, and beautiful typography.
example/lib/main.dart
import 'package:common_designs/common_designs.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Vendor Design System Example',
debugShowCheckedModeBanner: false,
theme: AppTheme.light(),
darkTheme: AppTheme.dark(),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Design System Examples'),
),
body: AnimatedListView(
padding: AppSpacing.allSM,
itemCount: _examples.length,
itemBuilder: (context, index) {
final example = _examples[index];
return Pressable(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => example.screen),
),
child: Card(
margin: const EdgeInsets.only(bottom: 12),
child: Padding(
padding: AppSpacing.allSM,
child: Row(
children: [
Icon(
example.icon,
color: AppColors.primary,
size: 32,
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
example.title,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 4),
Text(
example.description,
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
const Icon(Icons.chevron_right),
],
),
),
),
);
},
),
);
}
}
class Example {
final String title;
final String description;
final IconData icon;
final Widget screen;
Example({
required this.title,
required this.description,
required this.icon,
required this.screen,
});
}
final List<Example> _examples = [
Example(
title: 'Buttons & Interactions',
description: 'Pressable buttons, like buttons, and more',
icon: Icons.touch_app,
screen: const ButtonsExample(),
),
Example(
title: 'Modal Animations',
description: 'Bottom sheets with margins and animations',
icon: Icons.layers,
screen: const ModalExample(),
),
Example(
title: 'Chat Suggestions',
description: 'Auto-staggering suggestion chips',
icon: Icons.chat,
screen: const ChatExample(),
),
Example(
title: 'Typography',
description: 'All text styles and fonts',
icon: Icons.text_fields,
screen: const TypographyExample(),
),
Example(
title: 'Colors',
description: 'Color palette and gradients',
icon: Icons.palette,
screen: const ColorsExample(),
),
];
// Example Screens
class ButtonsExample extends StatefulWidget {
const ButtonsExample({super.key});
@override
State<ButtonsExample> createState() => _ButtonsExampleState();
}
class _ButtonsExampleState extends State<ButtonsExample> {
bool isLiked = false;
bool hasError = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Buttons & Interactions')),
body: ListView(
padding: AppSpacing.allLG,
children: [
Text('Pressable Button', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Pressable(
onPressed: () {},
child: Container(
padding: AppSpacing.allSM,
decoration: BoxDecoration(
color: AppColors.primary,
borderRadius: AppBorderRadius.md,
),
child: Center(
child: Text(
'Press Me',
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(color: Colors.white),
),
),
),
),
const SizedBox(height: 32),
Text('Like Button', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Center(
child: LikeButton(
isLiked: isLiked,
onTap: () => setState(() => isLiked = !isLiked),
likedColor: AppColors.like,
size: 48,
),
),
const SizedBox(height: 32),
Text('Shake Animation (Error)', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
ShakeWidget(
shake: hasError,
child: TextField(
decoration: InputDecoration(
labelText: 'Email',
errorText: hasError ? 'Invalid email' : null,
),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => setState(() => hasError = !hasError),
child: Text(hasError ? 'Clear Error' : 'Show Error'),
),
],
),
);
}
}
class ModalExample extends StatelessWidget {
const ModalExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Modal Animations')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
AppModals.showBottomSheetWithMargin(
context: context,
child: AppModalSheet(
title: 'Example Modal',
child: const Padding(
padding: EdgeInsets.all(16),
child: Text('This is a modal with margins at the bottom!'),
),
),
);
},
child: const Text('Show Modal with Margin'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
AppModals.showAlertDialog(
context: context,
title: 'Confirm',
content: 'Are you sure?',
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text('Confirm'),
),
],
);
},
child: const Text('Show Alert Dialog'),
),
],
),
),
);
}
}
class ChatExample extends StatefulWidget {
const ChatExample({super.key});
@override
State<ChatExample> createState() => _ChatExampleState();
}
class _ChatExampleState extends State<ChatExample> {
final TextEditingController _controller = TextEditingController();
bool _showSuggestions = true;
final List<String> _suggestions = [
'Hello! How can I help?',
'Track my order',
'Return policy',
'Contact support',
];
@override
void initState() {
super.initState();
_controller.addListener(() {
setState(() {
_showSuggestions = _controller.text.isEmpty;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Chat Suggestions')),
body: Column(
children: [
Expanded(
child: Center(
child: Text(
_showSuggestions
? 'Suggestions shown below'
: 'Start typing to hide suggestions',
style: Theme.of(context).textTheme.bodyLarge,
),
),
),
AnimatedSize(
duration: AnimationConfigs.medium,
child: _showSuggestions
? Padding(
padding: AppSpacing.allSM,
child: ChatSuggestions(
suggestions: _suggestions,
show: _showSuggestions,
onSuggestionTapped: (suggestion) {
_controller.text = suggestion;
},
),
)
: const SizedBox.shrink(),
),
Container(
padding: AppSpacing.allSM,
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
boxShadow: AppShadows.small,
),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Type a message...',
),
),
),
const SizedBox(width: 8),
IconButton(
onPressed: () => _controller.clear(),
icon: const Icon(Icons.send),
color: AppColors.primary,
),
],
),
),
],
),
);
}
}
class TypographyExample extends StatelessWidget {
const TypographyExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Typography')),
body: ListView(
padding: AppSpacing.allLG,
children: [
Text('Display Large', style: AppTypography.displayLarge()),
Text('Display Medium', style: AppTypography.displayMedium()),
Text('Display Small', style: AppTypography.displaySmall()),
const Divider(height: 32),
Text('Headline Large', style: AppTypography.headlineLarge()),
Text('Headline Medium', style: AppTypography.headlineMedium()),
Text('Headline Small', style: AppTypography.headlineSmall()),
const Divider(height: 32),
Text('Title Large', style: AppTypography.titleLarge()),
Text('Title Medium', style: AppTypography.titleMedium()),
Text('Title Small', style: AppTypography.titleSmall()),
const Divider(height: 32),
Text('Body Large', style: AppTypography.bodyLarge()),
Text('Body Medium', style: AppTypography.bodyMedium()),
Text('Body Small', style: AppTypography.bodySmall()),
const Divider(height: 32),
Text('Label Large', style: AppTypography.labelLarge()),
Text('Label Medium', style: AppTypography.labelMedium()),
Text('Label Small', style: AppTypography.labelSmall()),
const Divider(height: 32),
Text('\$55.00', style: AppTypography.price()),
Text('\$120.00', style: AppTypography.originalPrice()),
Text('4.8 ★', style: AppTypography.rating()),
],
),
);
}
}
class ColorsExample extends StatelessWidget {
const ColorsExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Colors')),
body: GridView.count(
crossAxisCount: 2,
padding: AppSpacing.allLG,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
children: [
_ColorBox('Primary', AppColors.primary),
_ColorBox('Primary Dark', AppColors.primaryDark),
_ColorBox('Primary Light', AppColors.primaryLight),
_ColorBox('Accent', AppColors.accent),
_ColorBox('Success', AppColors.success),
_ColorBox('Error', AppColors.error),
_ColorBox('Warning', AppColors.warning),
_ColorBox('Info', AppColors.info),
],
),
);
}
}
class _ColorBox extends StatelessWidget {
final String name;
final Color color;
const _ColorBox(this.name, this.color);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: color,
borderRadius: AppBorderRadius.md,
boxShadow: AppShadows.small,
),
child: Center(
child: Text(
name,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Colors.white,
shadows: [
const Shadow(
blurRadius: 4,
color: Colors.black26,
),
],
),
),
),
);
}
}