Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions lib/vaahextendflutter/widgets/atoms/app_expansion_panel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import 'package:flutter/material.dart' hide ExpansionPanel;
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:team/vaahextendflutter/app_theme.dart';

final _expansionTween = CurveTween(curve: Curves.fastOutSlowIn);
final _iconTurnTween = Tween<double>(begin: 0.0, end: 0.5) //
.chain(_expansionTween);

abstract class ExpansionControl {
abstract bool expanded;
}

typedef ExpansionHeaderBuilder = Widget Function(BuildContext context, ExpansionControl control);

@immutable
class AppExpansionPanel extends StatefulWidget {
const AppExpansionPanel({
Key? key,
required this.headerBuilder,
required this.children,
this.expanded = false,
this.padding = EdgeInsets.zero,
this.border = true,
this.textStyle,
}) : super(key: key);

final ExpansionHeaderBuilder headerBuilder;
final List<Widget> children;
final bool expanded;
final EdgeInsets padding;
final bool border;
final TextStyle? textStyle;

@override
State<AppExpansionPanel> createState() => _AppExpansionPanelState();
}

class _AppExpansionPanelState extends State<AppExpansionPanel>
with SingleTickerProviderStateMixin, ExpansionControl {
late AnimationController _controller;
late Animation<double> _expansionAnim;
late Animation<double> _iconTurns;

late bool _expanded;

@override
void initState() {
super.initState();
_expanded = widget.expanded;
_controller = AnimationController(duration: const Duration(milliseconds: 250), vsync: this);
_controller.value = expanded ? _controller.upperBound : _controller.lowerBound;
_expansionAnim = _controller.drive(_expansionTween);
_iconTurns = _controller.drive(_iconTurnTween);
}

@override
void didUpdateWidget(covariant AppExpansionPanel oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.expanded != widget.expanded) {
expanded = widget.expanded;
}
}

@override
bool get expanded => _expanded;

@override
set expanded(bool value) {
if (_expanded == value) return;

if (value) {
_controller.forward();
} else {
_controller.reverse();
}
_expanded = value;
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Material(
type: widget.border ? MaterialType.canvas : MaterialType.transparency,
shape: widget.border ? AppTheme.panelBorder : null,
textStyle: widget.textStyle,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
widget.headerBuilder(context, this),
SizeTransition(
axis: Axis.vertical,
axisAlignment: -1.0,
sizeFactor: _expansionAnim,
child: Padding(
padding: widget.padding - EdgeInsets.only(top: widget.padding.top),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: widget.children,
),
),
),
],
),
);
}
}

@immutable
class AppExpansionPanelIcon extends StatelessWidget {
const AppExpansionPanelIcon({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return RotationTransition(
turns: context.findAncestorStateOfType<_AppExpansionPanelState>()!._iconTurns,
child: FaIcon(
FontAwesomeIcons.angleDown,
color: AppTheme.colors['primary'],
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:team/vaahextendflutter/helpers/constants.dart';

class ContainerWithRoundedBorder extends StatelessWidget {
final EdgeInsets padding;
final double? width;
final double? height;
final double borderRadius;
final Color color;
final Widget child;

const ContainerWithRoundedBorder({
super.key,
this.padding = allPadding24,
this.width,
this.height,
this.borderRadius = defaultPadding,
this.color = Colors.white,
required this.child,
});

@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
padding: padding,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
color: color,
),
child: child,
);
}
}
20 changes: 20 additions & 0 deletions lib/views/pages/ui/components/commons.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:team/vaahextendflutter/app_theme.dart';

TextStyle heading = TextStyle(
fontSize: AppTheme.large,
fontWeight: FontWeight.bold,
color: AppTheme.colors['black']!.shade400,
);

TextStyle subheading = TextStyle(
fontSize: AppTheme.medium,
fontWeight: FontWeight.w600,
color: AppTheme.colors['black']!.shade400,
);

TextStyle normal = TextStyle(
fontSize: AppTheme.small,
fontWeight: FontWeight.w600,
color: AppTheme.colors['black']!.shade400,
);
21 changes: 21 additions & 0 deletions lib/views/pages/ui/components/section_title_selector.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:flutter/material.dart';
import 'package:team/vaahextendflutter/app_theme.dart';
import 'package:team/vaahextendflutter/helpers/styles.dart';

Widget sectionTitleSelector({
required String title,
bool condition = false,
required Function()? callback,
}) {
return InkWell(
onTap: callback,
child: Text(
title,
style: condition
? TextStyles.semiBold6?.copyWith(
color: AppTheme.colors['primary'],
)
: TextStyles.regular5,
),
);
}