diff --git a/packages/cave/lib/constants.dart b/packages/cave/lib/constants.dart index 45b8621..2449f29 100644 --- a/packages/cave/lib/constants.dart +++ b/packages/cave/lib/constants.dart @@ -4,6 +4,7 @@ abstract class Constants { static const horizontalMargin = 24.0; static const horizontalGutter = 8.0; + static const largeHorizontalGutter = 16.0; static const largeVerticalGutter = 24.0; static const verticalGutter = 16.0; static const smallVerticalGutter = 8.0; diff --git a/packages/cave/lib/themes/colors.dart b/packages/cave/lib/themes/colors.dart index db6a08c..c0e83b5 100644 --- a/packages/cave/lib/themes/colors.dart +++ b/packages/cave/lib/themes/colors.dart @@ -4,6 +4,9 @@ abstract class DevfestColors { static const gradientGradient = LinearGradient(colors: [Color(0xffc471ed), Color(0xff12c2e9)]); + static const inverseGradientGradient = + LinearGradient(colors: [Color(0xff12c2e9), Color(0xffc471ed)]); + static const Color grey10 = Color(0xff0a0a0a); static const Color grey20 = Color(0xff1d1d1d); diff --git a/packages/conferenceapp/assets/svgs/Google.svg b/packages/conferenceapp/assets/svgs/Google.svg new file mode 100644 index 0000000..00c7065 --- /dev/null +++ b/packages/conferenceapp/assets/svgs/Google.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/conferenceapp/lib/conference_app.dart b/packages/conferenceapp/lib/conference_app.dart index 382e46b..317f98f 100644 --- a/packages/conferenceapp/lib/conference_app.dart +++ b/packages/conferenceapp/lib/conference_app.dart @@ -36,7 +36,11 @@ class _ConferenceAppState extends ConsumerState { return MaterialApp.router( title: 'Devfest24 Conference App', routerConfig: Devfest2024Router.instance.router, - builder: (context, child) => AccessibilityTools(child: child), + builder: (context, child) => AccessibilityTools( + minimumTapAreas: const MinimumTapAreas(mobile: 30, desktop: 44), + checkFontOverflows: true, + child: child, + ), theme: ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.deepPurple, diff --git a/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart b/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart index 3ffac75..3721726 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart @@ -62,23 +62,23 @@ class _ViewState extends State<_View> { items: const [ DevfestBottomNavItem( label: 'Home', - icon: Icon(Icons.home), + icon: Icon(IconsaxOutline.home_2), ), DevfestBottomNavItem( label: 'Schedule', - icon: Icon(Icons.home), + icon: Icon(IconsaxOutline.calendar_1), ), DevfestBottomNavItem( label: 'Speakers', - icon: Icon(Icons.home), + icon: Icon(IconsaxOutline.microphone), ), DevfestBottomNavItem( label: 'Reserve', - icon: Icon(Icons.home), + icon: Icon(IconsaxOutline.ticket), ), DevfestBottomNavItem( label: 'More', - icon: Icon(Icons.home), + icon: Icon(IconsaxOutline.more_square), ), ], ), diff --git a/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart index 951deb2..1466e2b 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart @@ -45,12 +45,37 @@ class _HomeScreenState extends State { onFilterSelected: () {}, ), ), + SliverList.separated( + itemCount: 2, + itemBuilder: (context, index) => AgendaScheduleTile( + onTap: () {}, + ), + separatorBuilder: (context, _) => + Constants.smallVerticalGutter.verticalSpace, + ), SliverToBoxAdapter( - child: Container( - color: Colors.green, - height: 500, + child: Padding( + padding: + const EdgeInsets.only(top: Constants.verticalGutter).h, + child: InkWell( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: Constants.smallVerticalGutter) + .r, + child: const Center( + child: IconText( + Icons.arrow_forward, + 'View All Schedules', + alignment: IconTextAlignment.right, + ), + ), + ), + ), ), ), + SliverToBoxAdapter( + child: Constants.verticalGutter.verticalSpace), ], ), SliverMainAxisGroup( @@ -61,12 +86,55 @@ class _HomeScreenState extends State { onEventDayChanged: (day) {}, ), ), + SliverList.separated( + itemCount: 2, + itemBuilder: (context, index) => AgentTalkTile( + onTap: () {}, + ), + separatorBuilder: (context, _) => + Constants.smallVerticalGutter.verticalSpace, + ), SliverToBoxAdapter( - child: Container( - color: Colors.pink, - height: 800, + child: Padding( + padding: + const EdgeInsets.only(top: Constants.verticalGutter).h, + child: InkWell( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: Constants.smallVerticalGutter) + .r, + child: const Center( + child: IconText( + Icons.arrow_forward, + 'View All Talks', + alignment: IconTextAlignment.right, + ), + ), + ), + ), ), ), + SliverToBoxAdapter( + child: Constants.verticalGutter.verticalSpace), + ], + ), + SliverMainAxisGroup( + slivers: [ + const PinnedHeaderSliver( + child: HomeAgendaHeader( + title: Text('🥺 Sponsors'), + ), + ), + SliverList.separated( + itemCount: 4, + itemBuilder: (context, index) => + const ConferenceSponsorTile(), + separatorBuilder: (context, _) => + Constants.smallVerticalGutter.verticalSpace, + ), + SliverToBoxAdapter( + child: Constants.verticalGutter.verticalSpace), ], ), ], diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/agent_talk_tile.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/agent_talk_tile.dart new file mode 100644 index 0000000..8d98f03 --- /dev/null +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/agent_talk_tile.dart @@ -0,0 +1,193 @@ +import 'package:cave/cave.dart'; +import 'package:cave/constants.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:intl/intl.dart'; + +import '../../../../shared/shared.dart'; + +class AgentTalkTile extends StatelessWidget { + const AgentTalkTile({super.key, this.onTap}); + + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + final dateFormat = DateFormat('hh:mm a'); + return Material( + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all( + Radius.circular(Constants.verticalGutter), + ), + side: BorderSide( + color: DevfestColors.grey70.possibleDarkVariant, + width: 2, + ), + ), + child: InkWell( + onTap: onTap, + customBorder: RoundedRectangleBorder( + borderRadius: const BorderRadius.all( + Radius.circular(Constants.verticalGutter), + ), + side: BorderSide( + color: DevfestColors.grey70.possibleDarkVariant, + width: 2, + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: Constants.largeHorizontalGutter, vertical: 14) + .r, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'mobile development'.toUpperCase(), + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody3Medium + ?.medium + .applyColor(DevfestColors.grey60.possibleDarkVariant), + ), + FavouriteIcon( + onTap: () {}, + ), + ], + ), + Constants.verticalGutter.verticalSpace, + Text( + 'Appreciating the usefulness of football memes in decoding intent', + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody1Semibold + ?.semi + .applyColor(DevfestColors.grey10.possibleDarkVariant), + ), + Constants.smallVerticalGutter.verticalSpace, + Text( + 'Celebrate the women tech makers at their annual breakfast', + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody2Medium + ?.semi + .applyColor(DevfestColors.grey50.possibleDarkVariant), + ), + Constants.verticalGutter.verticalSpace, + const SpeakerInfo( + name: 'Samuel Abada', + shortBio: 'Flutter Engineer, Tesla', + avatarUrl: '', + ), + Constants.verticalGutter.verticalSpace, + Row( + children: [ + IconText( + IconsaxOutline.clock, + dateFormat.format(DateTime.now()), + ), + Constants.largeHorizontalGutter.horizontalSpace, + const IconText(IconsaxOutline.location, 'Hall A') + ], + ), + ], + ), + ), + ), + ); + } +} + +class SpeakerInfo extends StatelessWidget { + const SpeakerInfo({ + super.key, + this.avatarUrl = '', + required this.name, + required this.shortBio, + }); + + final String name; + final String shortBio; + final String avatarUrl; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Material( + color: DevfestColors.primariesGreen80, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(Constants.smallVerticalGutter), + ), + side: BorderSide(color: DevfestColors.primariesBlue50, width: 2), + ), + child: Padding( + padding: EdgeInsets.all(2), + child: FlutterLogo(size: 48), + ), + ), + Constants.horizontalGutter.horizontalSpace, + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: + DevfestTheme.of(context).textTheme?.bodyBody1Semibold?.semi, + ), + (Constants.smallVerticalGutter / 2).verticalSpace, + Text( + shortBio, + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody3Medium + ?.medium + .applyColor(DevfestColors.grey50.possibleDarkVariant), + ), + ], + ), + ), + ], + ); + } +} + +class FavouriteIcon extends StatelessWidget { + const FavouriteIcon({super.key, this.isFavourite = false, this.onTap}); + + final bool isFavourite; + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return Semantics.fromProperties( + properties: SemanticsProperties( + label: isFavourite ? 'Remove from favourites' : 'Add to favourites', + ), + child: Material( + borderRadius: const BorderRadius.all( + Radius.circular(Constants.smallVerticalGutter)), + color: DevfestColors.primariesYellow90.possibleDarkVariant, + child: InkWell( + onTap: onTap, + borderRadius: const BorderRadius.all( + Radius.circular(Constants.smallVerticalGutter)), + child: Padding( + padding: const EdgeInsets.all(Constants.largeVerticalGutter / 4).r, + child: Icon( + isFavourite ? IconsaxBold.star : IconsaxOutline.star, + color: DevfestColors.grey50.possibleDarkVariant, + ), + ), + ), + ), + ); + } +} diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart new file mode 100644 index 0000000..b53260e --- /dev/null +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart @@ -0,0 +1,103 @@ +import 'package:cave/cave.dart'; +import 'package:cave/constants.dart'; +import 'package:devfest24/src/shared/extensions.dart'; +import 'package:devfest24/src/shared/widgets/icon_text.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class AgendaScheduleTile extends StatelessWidget { + const AgendaScheduleTile({super.key, this.onTap}); + + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + final dateFormat = DateFormat('hh:mm a'); + return Material( + shape: RoundedRectangleBorder( + borderRadius: + const BorderRadius.all(Radius.circular(Constants.verticalGutter)), + side: BorderSide( + color: DevfestColors.grey70.possibleDarkVariant, width: 2), + ), + child: InkWell( + onTap: onTap, + customBorder: RoundedRectangleBorder( + borderRadius: + const BorderRadius.all(Radius.circular(Constants.verticalGutter)), + side: BorderSide( + color: DevfestColors.grey70.possibleDarkVariant, width: 2), + ), + child: Padding( + padding: EdgeInsets.all(Constants.verticalGutter.r), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const _Initials(initial: 'W'), + Constants.verticalGutter.verticalSpace, + Text( + '😘 Women Tech Makers Breakfast', + style: DevfestTheme.of(context) + .textTheme + ?.titleTitle2Semibold + ?.semi, + ), + Constants.smallVerticalGutter.verticalSpace, + Text( + 'Celebrate the women tech makers at their annual breakfast', + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody2Medium + ?.medium + .copyWith(color: DevfestColors.grey50.possibleDarkVariant), + ), + Constants.verticalGutter.verticalSpace, + Row( + children: [ + IconText( + IconsaxOutline.clock, + dateFormat.format(DateTime.now()), + ), + Constants.largeHorizontalGutter.horizontalSpace, + const IconText(IconsaxOutline.location, 'Hall A') + ], + ), + ], + ), + ), + ), + ); + } +} + +class _Initials extends StatelessWidget { + const _Initials({required this.initial}); + + final String initial; + + @override + Widget build(BuildContext context) { + return Material( + color: DevfestColors.primariesBlue80.possibleDarkVariant, + borderRadius: const BorderRadius.all( + Radius.circular(Constants.smallVerticalGutter)), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: Constants.smallVerticalGutter, + horizontal: Constants.largeVerticalGutter / 2, + ).r, + child: Text( + initial.toUpperCase(), + textAlign: TextAlign.center, + style: DevfestTheme.of(context) + .textTheme + ?.titleTitle1Semibold + ?.semi + .copyWith( + color: DevfestColors.primariesBlue20.possibleDarkVariant, + height: 1.34), + ), + ), + ); + } +} diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart new file mode 100644 index 0000000..eb0ad78 --- /dev/null +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart @@ -0,0 +1,128 @@ +import 'package:cave/cave.dart'; +import 'package:cave/constants.dart'; +import 'package:devfest24/src/shared/shared.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class ConferenceSponsorTile extends StatelessWidget { + const ConferenceSponsorTile({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ConstrainedBox( + constraints: BoxConstraints(minHeight: 160.r), + child: DecoratedBox( + decoration: const BoxDecoration( + gradient: DevfestColors.inverseGradientGradient, + color: Colors.green, + borderRadius: BorderRadius.all( + Radius.circular(Constants.smallVerticalGutter)), + ), + child: Padding( + padding: const EdgeInsets.all(Constants.smallVerticalGutter).r, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const _SponsorTierTag('Platinum Sponsor'), + Padding( + padding: const EdgeInsets.symmetric( + vertical: Constants.largeVerticalGutter) + .h, + child: Center( + child: SvgPicture.asset( + 'assets/svgs/Google.svg', + ), + ), + ), + Align( + alignment: Alignment.bottomRight, + child: _SponsorLinkTag( + () {}, + ), + ) + ], + ), + ), + ), + ), + Constants.smallVerticalGutter.verticalSpace, + Text( + 'Google', + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody1Medium + ?.medium + .applyColor(DevfestColors.grey30.possibleDarkVariant), + ), + ], + ); + } +} + +class _SponsorTierTag extends StatelessWidget { + const _SponsorTierTag(this.tagName); + + final String tagName; + + @override + Widget build(BuildContext context) { + return Material( + color: DevfestColors.backgroundSoftLight, + shape: const RoundedRectangleBorder( + borderRadius: + BorderRadius.all(Radius.circular(Constants.smallVerticalGutter)), + side: BorderSide( + color: DevfestColors.grey100, + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: Constants.horizontalGutter, + vertical: Constants.smallVerticalGutter / 2) + .r, + child: Text( + tagName, + style: DevfestTheme.of(context) + .textTheme + ?.bodyBody3Medium + ?.medium + .applyColor(DevfestColors.grey100), + ), + ), + ); + } +} + +class _SponsorLinkTag extends StatelessWidget { + const _SponsorLinkTag(this.onTap); + + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return Material( + color: DevfestColors.backgroundSoftLight, + shape: const CircleBorder( + side: BorderSide(color: DevfestColors.grey100), + ), + child: InkWell( + onTap: onTap, + customBorder: const CircleBorder( + side: BorderSide(color: DevfestColors.grey100), + ), + child: Padding( + padding: const EdgeInsets.all(Constants.largeVerticalGutter / 4).r, + child: Icon( + IconsaxOutline.link, + size: 12.r, + color: DevfestColors.grey100, + ), + ), + ), + ); + } +} diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/widgets.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/widgets.dart index 4005652..f5d0ce7 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/widgets/widgets.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/widgets.dart @@ -1,2 +1,6 @@ //GENERATED BARREL FILE export 'agenda_header.dart'; +export 'agent_talk_tile.dart'; +export 'schedule_tile.dart'; +export 'sponsor_tile.dart'; + diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/presentation.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/presentation.dart index f502f3b..7a42dc6 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/presentation.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/presentation.dart @@ -1,2 +1,4 @@ //GENERATED BARREL FILE export './screens/screens.dart'; +export './widgets/widgets.dart'; + diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/widgets.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/widgets.dart new file mode 100644 index 0000000..1e4a469 --- /dev/null +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/widgets.dart @@ -0,0 +1 @@ +//GENERATED BARREL FILE diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/presentation.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/presentation.dart index f502f3b..7a42dc6 100644 --- a/packages/conferenceapp/lib/src/features/speakers/presentation/presentation.dart +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/presentation.dart @@ -1,2 +1,4 @@ //GENERATED BARREL FILE export './screens/screens.dart'; +export './widgets/widgets.dart'; + diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/widgets.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/widgets.dart new file mode 100644 index 0000000..1e4a469 --- /dev/null +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/widgets.dart @@ -0,0 +1 @@ +//GENERATED BARREL FILE diff --git a/packages/conferenceapp/lib/src/shared/extensions.dart b/packages/conferenceapp/lib/src/shared/extensions.dart index 24a9638..3e4fdc9 100644 --- a/packages/conferenceapp/lib/src/shared/extensions.dart +++ b/packages/conferenceapp/lib/src/shared/extensions.dart @@ -15,6 +15,7 @@ extension DevfestColorsX on Color { return switch (this) { DevfestColors.grey40 || DevfestColors.grey60 => DevfestColors.grey70, DevfestColors.grey10 => DevfestColors.backgroundLight, + DevfestColors.grey70 => DevfestColors.grey50, // DevfestColors.grey50 => DevfestColors.primariesYellow90 => DevfestColors.grey40, DevfestColors.primariesYellow100 => DevfestColors.backgroundDark, diff --git a/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart b/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart index 20d7178..251457a 100644 --- a/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart +++ b/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart @@ -43,10 +43,11 @@ class AgendaHeader extends StatelessWidget { : SizedBox( width: 87.w, child: DevfestFilledButton.small( + onPressed: onFilterSelected, backgroundColor: DevfestColors.primariesYellow90.possibleDarkVariant, prefixIcon: Icon( - Icons.filter_alt_outlined, + IconsaxOutline.filter, color: DevfestTheme.of(context) .textTheme ?.titleTitle2Semibold @@ -69,30 +70,32 @@ class AgendaHeader extends StatelessWidget { ?.medium .applyColor(DevfestColors.grey50.possibleDarkVariant), ), - gutter ?? Constants.largeVerticalGutter.verticalSpace, - Row( - children: [ - Flexible( - child: DevfestTabButton( - title: const Text('Friday'), - selected: eventDay == EventDay.one, - onTap: () { - onEventDayChanged?.call(EventDay.one); - }, + if (onEventDayChanged != null) ...[ + gutter ?? Constants.largeVerticalGutter.verticalSpace, + Row( + children: [ + Flexible( + child: DevfestTabButton( + title: const Text('Friday'), + selected: eventDay == EventDay.one, + onTap: () { + onEventDayChanged?.call(EventDay.one); + }, + ), ), - ), - Flexible( - child: DevfestTabButton( - title: const Text('Saturday'), - selected: eventDay == EventDay.two, - onTap: () { - onEventDayChanged?.call(EventDay.two); - }, + Flexible( + child: DevfestTabButton( + title: const Text('Saturday'), + selected: eventDay == EventDay.two, + onTap: () { + onEventDayChanged?.call(EventDay.two); + }, + ), ), - ), - ], - ), - Constants.verticalGutter.verticalSpace, + ], + ), + Constants.verticalGutter.verticalSpace, + ], ], ); } diff --git a/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart b/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart index 80dc3c7..31102fc 100644 --- a/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart +++ b/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart @@ -12,7 +12,7 @@ class CheckInButton extends StatelessWidget { width: 113.w, child: DevfestFilledButton.small( onPressed: onTap, - prefixIcon: const Icon(Icons.shield_outlined, size: 20), + prefixIcon: const Icon(IconsaxOutline.shield, size: 20), title: const Text( 'Check-In', ), diff --git a/packages/conferenceapp/lib/src/shared/widgets/icon_text.dart b/packages/conferenceapp/lib/src/shared/widgets/icon_text.dart new file mode 100644 index 0000000..8365f46 --- /dev/null +++ b/packages/conferenceapp/lib/src/shared/widgets/icon_text.dart @@ -0,0 +1,70 @@ +import 'package:cave/cave.dart'; +import 'package:cave/constants.dart'; +import 'package:flutter/material.dart'; + +enum IconTextAlignment { left, right } + +class IconText extends StatelessWidget { + const IconText( + this.icon, + this.text, { + super.key, + this.gap = Constants.horizontalGutter, + this.iconSize = 20, + this.iconColor, + this.textStyle, + this.textAlign, + this.alignment = IconTextAlignment.left, + }); + + final IconData icon; + final String text; + final double gap; + final TextStyle? textStyle; + final TextAlign? textAlign; + final double iconSize; + final Color? iconColor; + final IconTextAlignment alignment; + + @override + Widget build(BuildContext context) { + final gap = Constants.horizontalGutter.horizontalSpace; + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + ...switch (alignment) { + IconTextAlignment.left => [ + _buildIcon(), + gap, + _buildText(context), + ], + IconTextAlignment.right => [ + _buildText(context), + gap, + _buildIcon(), + ], + }, + ], + ); + } + + Widget _buildIcon() { + return Icon( + icon, + size: iconSize, + color: iconColor, + ); + } + + Widget _buildText(BuildContext context) { + return AnimatedDefaultTextStyle( + style: DevfestTheme.of(context).textTheme!.bodyBody3Medium!.medium, + duration: Constants.kAnimationDur, + child: Text( + text, + style: textStyle, + textAlign: textAlign, + ), + ); + } +} diff --git a/packages/conferenceapp/lib/src/shared/widgets/widgets.dart b/packages/conferenceapp/lib/src/shared/widgets/widgets.dart index 5e4eb51..c03f012 100644 --- a/packages/conferenceapp/lib/src/shared/widgets/widgets.dart +++ b/packages/conferenceapp/lib/src/shared/widgets/widgets.dart @@ -2,5 +2,7 @@ export 'agenda_header.dart'; export 'check_in_button.dart'; export 'header.dart'; +export 'icon_text.dart'; export 'keep_alive_widget.dart'; export 'tab_button.dart'; + diff --git a/packages/conferenceapp/pubspec.lock b/packages/conferenceapp/pubspec.lock index a86f3e3..e93ff54 100644 --- a/packages/conferenceapp/pubspec.lock +++ b/packages/conferenceapp/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" async: dependency: transitive description: @@ -133,6 +141,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.9.3" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -167,6 +183,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" leak_tracker: dependency: transitive description: @@ -255,6 +279,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" plugin_platform_interface: dependency: transitive description: @@ -340,6 +380,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -372,6 +436,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.5.4" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" sdks: dart: ">=3.4.4 <4.0.0" flutter: ">=3.22.0" diff --git a/packages/conferenceapp/pubspec.yaml b/packages/conferenceapp/pubspec.yaml index b66a4d6..e592345 100644 --- a/packages/conferenceapp/pubspec.yaml +++ b/packages/conferenceapp/pubspec.yaml @@ -21,6 +21,8 @@ dependencies: flutter_riverpod: ^2.5.1 accessibility_tools: ^2.2.2 package_info_plus: ^8.0.2 + intl: ^0.19.0 + flutter_svg: ^2.0.10+1 dev_dependencies: flutter_lints: ^4.0.0 @@ -31,6 +33,9 @@ dev_dependencies: # The following section is specific to Flutter packages. flutter: + assets: + - assets/svgs/ + # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class.