astra_ui 0.1.2
astra_ui: ^0.1.2 copied to clipboard
A beautiful modern Flutter UI component library with 37+ components. Includes buttons inputs chips avatars tabs and more. Inspired by shadcn/ui.
import 'package:flutter/material.dart';
import 'package:astra_ui/astra_ui.dart';
import 'package:device_preview/device_preview.dart';
void main() {
runApp(
DevicePreview(
enabled: true,
defaultDevice: Devices.android.samsungGalaxyNote20Ultra,
builder: (context) => const AstraUIExampleApp(),
),
);
}
class AstraUIExampleApp extends StatelessWidget {
const AstraUIExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AstraUI Example',
debugShowCheckedModeBanner: false,
locale: DevicePreview.locale(context),
builder: DevicePreview.appBuilder,
theme: ThemeData(
scaffoldBackgroundColor: AstraColors.offWhite,
useMaterial3: true,
),
home: const ExampleHomePage(),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key});
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _searchController = TextEditingController();
int selectedTab = 0;
@override
void dispose() {
_usernameController.dispose();
_emailController.dispose();
_passwordController.dispose();
_searchController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AstraColors.offWhite,
appBar: AppBar(
title: const Text(
'AstraUI Components',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: AstraColors.warmGray,
),
),
backgroundColor: Colors.white,
elevation: 0,
bottom: PreferredSize(
preferredSize: const Size.fromHeight(1),
child: Container(height: 1, color: AstraColors.lightGray),
),
),
body: Column(
children: [
// Navigation Tabs
Container(
color: Colors.white,
padding: const EdgeInsets.all(16),
child: AstraLineTabs(
selectedIndex: selectedTab,
tabs: const [
AstraLineTabItem(label: 'Buttons', icon: Icons.touch_app),
AstraLineTabItem(label: 'Inputs', icon: Icons.edit),
AstraLineTabItem(label: 'Chips', icon: Icons.label),
AstraLineTabItem(label: 'Avatars', icon: Icons.person),
AstraLineTabItem(label: 'More', icon: Icons.apps),
],
onTabChanged: (index) {
setState(() {
selectedTab = index;
});
},
),
),
// Content
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: _buildTabContent(),
),
),
],
),
);
}
Widget _buildTabContent() {
switch (selectedTab) {
case 0:
return _buildButtonsTab();
case 1:
return _buildInputsTab();
case 2:
return _buildChipsTab();
case 3:
return _buildAvatarsTab();
case 4:
return _buildMoreTab();
default:
return const SizedBox();
}
}
// BUTTONS TAB
Widget _buildButtonsTab() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_sectionTitle('Solid Button'),
AstraSolidButton(
label: 'Click Me',
onPressed: () {},
leftIcon: Icons.check,
),
const SizedBox(height: 24),
_sectionTitle('Outline Button'),
AstraOutlineButton(
label: 'Cancel',
onPressed: () {},
leftIcon: Icons.close,
),
const SizedBox(height: 24),
_sectionTitle('Ghost Button'),
AstraGhostButton(
label: 'Ghost',
onPressed: () {},
leftIcon: Icons.visibility,
),
const SizedBox(height: 24),
_sectionTitle('Destructive Button'),
AstraDestructiveButton(
label: 'Delete',
onPressed: () {},
leftIcon: Icons.delete,
),
const SizedBox(height: 24),
_sectionTitle('Link Button'),
AstraLinkButton(
label: 'Visit Website',
url: 'https://pub.dev/packages/astra_ui',
leftIcon: Icons.link,
),
],
);
}
// INPUTS TAB
Widget _buildInputsTab() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_sectionTitle('Text Input'),
AstraTextInput(
label: 'Username',
placeholder: 'Enter your username',
leftIcon: Icons.person,
controller: _usernameController,
),
const SizedBox(height: 24),
_sectionTitle('Email Input'),
AstraEmailInput(
label: 'Email',
placeholder: 'your@email.com',
controller: _emailController,
),
const SizedBox(height: 24),
_sectionTitle('Password Input'),
AstraPasswordInput(
label: 'Password',
placeholder: 'Enter password',
controller: _passwordController,
),
const SizedBox(height: 24),
_sectionTitle('Search Input'),
AstraSearchInput(
placeholder: 'Search...',
controller: _searchController,
),
const SizedBox(height: 16),
_sectionTitle('Search with Filter Icon'),
AstraSearchInput(
placeholder: 'Search products...',
controller: _searchController,
rightIcon: Icons.tune,
rightIconColor: AstraColors.mintGreen,
onRightIconTap: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Filter icon tapped!')),
);
},
),
const SizedBox(height: 24),
_sectionTitle('Toggle Switch'),
AstraToggle(
value: true,
onChanged: (value) {},
),
const SizedBox(height: 24),
_sectionTitle('Simple Dropdown'),
AstraSimpleDropdown<String>(
label: 'Select Country',
placeholder: 'Choose...',
items: const [
AstraDropdownItem(
value: 'us', label: 'United States', icon: Icons.flag),
AstraDropdownItem(
value: 'uk', label: 'United Kingdom', icon: Icons.flag),
AstraDropdownItem(value: 'ca', label: 'Canada', icon: Icons.flag),
],
onChanged: (value) {},
),
],
);
}
// CHIPS TAB
Widget _buildChipsTab() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_sectionTitle('Basic Chips'),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
AstraChip(
label: 'Default',
icon: Icons.star,
onDeleted: () {},
),
const AstraOutlineChip(
label: 'Outline',
icon: Icons.favorite,
),
const AstraSolidChip(
label: 'Solid',
icon: Icons.check,
),
],
),
const SizedBox(height: 24),
_sectionTitle('Choice Chips'),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
AstraChoiceChip(
label: 'Option 1',
selected: true,
onSelected: (value) {},
),
AstraChoiceChip(
label: 'Option 2',
selected: false,
onSelected: (value) {},
),
],
),
const SizedBox(height: 24),
_sectionTitle('Special Chips'),
Wrap(
spacing: 8,
runSpacing: 8,
children: const [
AstraGradientChip(
label: 'Gradient',
icon: Icons.auto_awesome,
),
AstraGlowChip(
label: 'Glow',
icon: Icons.lightbulb,
),
AstraPillChip(
label: 'Pill',
icon: Icons.medication,
),
],
),
const SizedBox(height: 24),
_sectionTitle('Icon Only Chips'),
Wrap(
spacing: 8,
runSpacing: 8,
children: const [
AstraIconOnlyChip(icon: Icons.home, size: 32),
AstraIconOnlyChip(icon: Icons.favorite, size: 32),
AstraIconOnlyChip(icon: Icons.star, size: 32),
],
),
],
);
}
// AVATARS TAB
Widget _buildAvatarsTab() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_sectionTitle('Basic Avatars'),
Wrap(
spacing: 16,
runSpacing: 16,
children: const [
AstraAvatar(initials: 'JD', size: 48),
AstraAvatar(
initials: 'AB',
size: 48,
backgroundColor: AstraColors.dustyRose,
),
AstraAvatar(
initials: 'XY',
size: 48,
backgroundColor: AstraColors.softPeach,
),
],
),
const SizedBox(height: 24),
_sectionTitle('Avatars with Images'),
Wrap(
spacing: 16,
runSpacing: 16,
children: const [
AstraAvatar(
imageUrl: 'https://i.pravatar.cc/150?img=1',
initials: 'JD',
size: 48,
),
AstraAvatar(
imageUrl: 'https://i.pravatar.cc/150?img=2',
initials: 'AB',
size: 48,
backgroundColor: AstraColors.dustyRose,
),
AstraAvatar(
imageUrl: 'https://i.pravatar.cc/150?img=3',
initials: 'XY',
size: 48,
backgroundColor: AstraColors.softPeach,
),
],
),
const SizedBox(height: 24),
_sectionTitle('Ring Avatars'),
Wrap(
spacing: 16,
runSpacing: 16,
children: const [
AstraRingAvatar(
initials: 'JD',
size: 48,
ringColor: AstraColors.mintGreen,
),
AstraRingAvatar(
initials: 'AB',
size: 48,
ringColor: AstraColors.dustyRose,
),
],
),
const SizedBox(height: 24),
_sectionTitle('Gradient Avatars'),
Wrap(
spacing: 16,
runSpacing: 16,
children: [
AstraGradientAvatar(initials: 'JD', size: 48),
AstraGradientAvatar(
initials: 'AB',
size: 48,
gradientColors: [AstraColors.dustyRose, AstraColors.softPeach],
),
],
),
const SizedBox(height: 24),
_sectionTitle('Status Avatars'),
Wrap(
spacing: 16,
runSpacing: 16,
children: [
AstraStatusAvatar.online(initials: 'JD', size: 48),
AstraStatusAvatar.busy(initials: 'AB', size: 48),
AstraStatusAvatar.away(initials: 'XY', size: 48),
AstraStatusAvatar.offline(initials: 'PQ', size: 48),
],
),
const SizedBox(height: 24),
_sectionTitle('Icon Avatars'),
Wrap(
spacing: 16,
runSpacing: 16,
children: const [
AstraIconAvatar(icon: Icons.person, size: 48),
AstraIconAvatar(
icon: Icons.business,
size: 48,
backgroundColor: AstraColors.dustyRose,
),
],
),
const SizedBox(height: 24),
_sectionTitle('Group Avatar'),
AstraGroupAvatar(
size: 40,
maxVisible: 3,
avatars: const [
AvatarData(initials: 'JD'),
AvatarData(initials: 'AB', backgroundColor: AstraColors.dustyRose),
AvatarData(initials: 'XY', backgroundColor: AstraColors.softPeach),
AvatarData(initials: 'PQ', backgroundColor: AstraColors.mintGreen),
AvatarData(initials: 'LM', backgroundColor: AstraColors.warmGray),
],
),
],
);
}
// MORE TAB (Tabs & Dropdowns)
Widget _buildMoreTab() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_sectionTitle('Line Tabs'),
AstraLineTabs(
selectedIndex: 0,
tabs: const [
AstraLineTabItem(label: 'Home', icon: Icons.home),
AstraLineTabItem(label: 'Profile', icon: Icons.person),
AstraLineTabItem(label: 'Settings', icon: Icons.settings),
],
onTabChanged: (index) {},
),
const SizedBox(height: 24),
_sectionTitle('Pill Tabs'),
AstraPillTabs(
selectedIndex: 0,
tabs: const [
AstraPillTabItem(label: 'All'),
AstraPillTabItem(label: 'Active'),
AstraPillTabItem(label: 'Completed'),
],
onTabChanged: (index) {},
),
const SizedBox(height: 24),
_sectionTitle('Segment Tabs'),
AstraSegmentTabs(
selectedIndex: 0,
tabs: const [
AstraSegmentTabItem(label: 'Day'),
AstraSegmentTabItem(label: 'Week'),
AstraSegmentTabItem(label: 'Month'),
],
onTabChanged: (index) {},
),
const SizedBox(height: 24),
_sectionTitle('Search Dropdown'),
AstraSearchDropdown<String>(
label: 'Search Country',
placeholder: 'Type to search...',
items: const [
AstraSearchDropdownItem(
value: 'us', label: 'United States', icon: Icons.flag),
AstraSearchDropdownItem(
value: 'uk', label: 'United Kingdom', icon: Icons.flag),
AstraSearchDropdownItem(
value: 'ca', label: 'Canada', icon: Icons.flag),
AstraSearchDropdownItem(
value: 'au', label: 'Australia', icon: Icons.flag),
AstraSearchDropdownItem(
value: 'de', label: 'Germany', icon: Icons.flag),
],
onChanged: (value) {},
),
],
);
}
Widget _sectionTitle(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AstraColors.warmGray,
),
),
);
}
}