wip: buat input component lib

# besok lanjut forms library (reactive form)
This commit is contained in:
Golek 2022-12-02 16:45:09 +07:00
parent 47c9386eb2
commit c9e784fb73
29 changed files with 287 additions and 725 deletions

View File

@ -2,6 +2,12 @@ PACKAGES := $(wildcard packages/*)
FEATURES := $(wildcard packages/features/*)
BUILD-RUNNER := packages/golektruk_api
run:
flutter run lib/main.dart
story:
flutter run packages/component_library/example/main.dart
intl:
flutter gen-l10n

View File

@ -1,9 +1,57 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:storybook_flutter/storybook_flutter.dart';
List<Story> getStories(GolekThemeData theme) {
return [
Story(
name: 'Plain Input Field',
section: 'Form Input',
builder: (_, k) => InputField(
errorMessage: k.text(label: 'errorMessage'),
placeholder: k.text(
label: 'placeholder',
initial: 'Placeholder',
),
label: k.text(label: 'Label', initial: 'Label'),
obscureText: k.boolean(label: 'obscureText', initial: false),
textInputType: k.options<TextInputType>(
label: 'textInputType',
initial: TextInputType.text,
options: [
const Option('Email', TextInputType.emailAddress),
const Option('Number', TextInputType.number),
const Option('Date Time', TextInputType.datetime),
]),
inputFormatters: k.options<List<TextInputFormatter>>(
label: 'inputFormatters',
initial: [],
options: [
Option(
'Maximum Text Input Formatter',
[LengthLimitingTextInputFormatter(12)],
),
Option(
'Regex Filter Text Input Formatter',
[FilteringTextInputFormatter.allow(RegExp(r'^[2-9][0-9]*'))],
),
],
),
isDisabled: k.boolean(
label: 'disabled',
initial: false,
),
isTouched: k.boolean(
label: 'touched',
initial: false,
),
isError: k.boolean(
label: 'error',
initial: false,
),
),
),
Story.simple(
name: 'Simple Expanded Elevated Button',
section: 'Buttons',
@ -27,7 +75,7 @@ List<Story> getStories(GolekThemeData theme) {
? () {}
: null,
icon: Icon(
k.options(
k.options<IconData>(
label: 'icon',
initial: Icons.home,
options: const [
@ -58,247 +106,5 @@ List<Story> getStories(GolekThemeData theme) {
),
),
),
Story(
name: 'InProgress Text Button',
section: 'Buttons',
builder: (_, k) => InProgressTextButton(
label: k.text(
label: 'label',
initial: 'Processing',
),
),
),
Story(
name: 'Favorite Button',
section: 'Buttons',
builder: (_, k) => FavoriteIconButton(
onTap: () {},
isFavorite: k.boolean(
label: 'isFavorite',
initial: false,
),
),
),
Story.simple(
name: 'Share Icon Button',
section: 'Buttons',
child: ShareIconButton(onTap: () {}),
),
Story(
name: 'Count Indicator Icon Button',
section: 'Count Indicator Buttons',
builder: (_, k) => CountIndicatorIconButton(
count: k.sliderInt(
label: 'count',
),
iconData: k.options(
label: 'iconData',
initial: Icons.arrow_upward,
options: const [
Option(
'Upward',
Icons.arrow_upward,
),
Option(
'Downward',
Icons.arrow_downward,
),
],
),
tooltip: k.text(
label: 'tooltip',
initial: 'Count indicator',
),
),
),
Story(
name: 'Exception Indicator',
section: 'Indicators',
builder: (_, k) => ExceptionIndicator(
title: k.text(
label: 'title',
initial: 'Exception title',
),
message: k.text(
label: 'message',
initial: 'Exception message',
),
onTryAgain: k.boolean(
label: 'onTryAgain',
initial: false,
)
? () {}
: null,
),
),
Story.simple(
name: 'Centered Circular Progress Indicator',
child: const CenteredCircularProgressIndicator(),
),
Story(
name: 'Rounded Choice Chip',
padding: const EdgeInsets.all(
Spacing.medium,
),
builder: (_, k) => RoundedChoiceChip(
label: k.text(
label: 'label',
initial: 'I am a Chip!',
),
isSelected: k.boolean(
label: 'isSelected',
initial: false,
),
avatar: k.boolean(
label: 'avatar',
initial: false,
)
? Icon(
Icons.favorite,
color: theme.warningMainColor,
)
: null,
onSelected: k.boolean(
label: 'onSelected',
initial: true,
)
? (_) {}
: null,
backgroundColor: k.options(
label: 'backgroundColor',
initial: null,
options: const [
Option(
'Light blue',
Colors.lightBlue,
),
Option(
'Red accent',
Colors.redAccent,
),
],
),
selectedBackgroundColor: k.options(
label: 'selectedBackgroundColor',
initial: null,
options: const [
Option(
'Green',
Colors.green,
),
Option(
'Amber accent',
Colors.amberAccent,
),
],
),
labelColor: k.options(
label: 'labelColor',
initial: null,
options: const [
Option(
'Teal',
Colors.teal,
),
Option(
'Orange accent',
Colors.orangeAccent,
),
],
),
selectedLabelColor: k.options(
label: 'selectedLabelColor',
initial: null,
options: const [
Option(
'Deep purple accent',
Colors.deepPurpleAccent,
),
Option(
'Amber accent',
Colors.amberAccent,
),
],
),
),
),
Story(
name: 'Chevron List Tile',
padding: const EdgeInsets.all(
Spacing.medium,
),
builder: (_, k) => ChevronListTile(
label: k.text(
label: 'label',
initial: 'Update Profile',
),
),
),
Story.simple(
name: 'Search Bar',
child: const SearchBar(),
),
Story(
name: 'Shrinkable Text',
builder: (_, k) => SafeArea(
child: ShrinkableText(
k.text(
label: 'text',
initial:
'I am shrinkable text. I can resize myself automatically within a space.',
),
style: k.options(
label: 'style',
initial: theme.textStyle.copyWith(
fontSize: FontSize.style24,
),
options: [
Option(
'XX large',
theme.textStyle.copyWith(
fontSize: FontSize.style24,
),
),
Option(
'Small',
theme.textStyle.copyWith(
fontSize: FontSize.style12,
),
),
],
),
textAlign: k.options(
label: 'textAlign',
initial: null,
options: const [
Option(
'Start',
TextAlign.start,
),
Option(
'End',
TextAlign.end,
),
Option(
'Center',
TextAlign.center,
),
Option(
'Justify',
TextAlign.justify,
),
Option(
'Left',
TextAlign.left,
),
Option(
'Right',
TextAlign.right,
),
],
),
),
),
),
];
}

View File

@ -2,7 +2,7 @@
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// gestures. You can also use WidgetTester to find child landing_page in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter_test/flutter_test.dart';

View File

@ -1,21 +1,9 @@
export 'src/chevron_list_tile.dart';
export 'src/count_indicator_icon_button.dart';
export 'src/downvote_icon_button.dart';
export 'src/exception_indicator.dart';
export 'src/expanded_elevated_button.dart';
export 'src/in_progress_text_button.dart';
export 'src/favorite_icon_button.dart';
export 'src/l10n/component_library_localizations.dart';
export 'src/centered_circular_progress_indicator.dart';
export 'src/rounded_choice_chip.dart';
export 'src/generic_error_snack_bar.dart';
export 'src/authentication_required_error_snack_bar.dart';
export 'src/row_app_bar.dart';
export 'src/search_bar.dart';
export 'src/share_icon_button.dart';
export 'src/shrinkable_text.dart';
export 'src/styled_status_bar.dart';
export 'src/theme/font_size.dart';
export 'src/theme/spacing.dart';
export 'src/theme/golek_theme.dart';
export 'src/theme/golek_theme_data.dart';
export 'src/input_field.dart';
export 'src/error_message_builder.dart';
export 'src/favorite_icon_button.dart';

View File

@ -1,23 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class AuthenticationRequiredErrorSnackBar extends SnackBar {
const AuthenticationRequiredErrorSnackBar({Key? key})
: super(
key: key,
content: const _AuthenticationRequiredErrorSnackBarMessage(),
);
}
class _AuthenticationRequiredErrorSnackBarMessage extends StatelessWidget {
const _AuthenticationRequiredErrorSnackBarMessage({Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
final l10n = ComponentLibraryLocalizations.of(context);
return Text(
l10n.authenticationRequiredErrorSnackbarMessage,
);
}
}

View File

@ -1,12 +0,0 @@
import 'package:flutter/material.dart';
class CenteredCircularProgressIndicator extends StatelessWidget {
const CenteredCircularProgressIndicator({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Center(
child: CircularProgressIndicator(),
);
}
}

View File

@ -1,29 +0,0 @@
import 'package:component_library/src/theme/font_size.dart';
import 'package:flutter/material.dart';
class ChevronListTile extends StatelessWidget {
const ChevronListTile({
required this.label,
this.onTap,
Key? key,
}) : super(key: key);
final String label;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(
label,
style: const TextStyle(
fontSize: FontSize.style18,
),
),
trailing: const Icon(
Icons.chevron_right_outlined,
),
onTap: onTap,
);
}
}

View File

@ -1,43 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class CountIndicatorIconButton extends StatelessWidget {
const CountIndicatorIconButton({
required this.count,
required this.iconData,
this.iconColor,
this.tooltip,
this.onTap,
Key? key,
}) : super(key: key);
final int count;
final IconData iconData;
final Color? iconColor;
final String? tooltip;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: onTap,
tooltip: tooltip,
padding: const EdgeInsets.all(0),
icon: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
iconData,
color: iconColor,
),
Text(
count.toString(),
style: const TextStyle(
fontSize: FontSize.style12,
),
),
],
),
);
}
}

View File

@ -1,29 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class DownvoteIconButton extends StatelessWidget {
const DownvoteIconButton({
required this.count,
required this.isDownvoted,
this.onTap,
Key? key,
}) : super(key: key);
final int count;
final VoidCallback? onTap;
final bool isDownvoted;
@override
Widget build(BuildContext context) {
final l10n = ComponentLibraryLocalizations.of(context);
final theme = GolekTheme.of(context);
return CountIndicatorIconButton(
onTap: onTap,
tooltip: l10n.downvoteIconButtonTooltip,
iconData: Icons.arrow_downward_sharp,
iconColor:
isDownvoted ? theme.warningMainColor : theme.neutral20Color,
count: count,
);
}
}

View File

@ -0,0 +1,28 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class ErrorMessageBuilder extends StatelessWidget {
const ErrorMessageBuilder({
Key? key,
required this.inputLabel,
required this.messageError,
}) : super(key: key);
/// input label ditampilkan title ketika error
final String inputLabel;
/// pesan error yang ditampilkan
final String messageError;
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return Text(
messageError,
style: theme.textStyle.copyWith(
fontSize: FontSize.style12,
color: theme.dangerMainColor,
),
);
}
}

View File

@ -1,67 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class ExceptionIndicator extends StatelessWidget {
const ExceptionIndicator({
this.title,
this.message,
this.onTryAgain,
Key? key,
}) : super(key: key);
final String? title;
final String? message;
final VoidCallback? onTryAgain;
@override
Widget build(BuildContext context) {
final l10n = ComponentLibraryLocalizations.of(context);
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 32,
horizontal: 16,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.error,
size: 48,
),
const SizedBox(
height: Spacing.xxLarge,
),
Text(
title ?? l10n.exceptionIndicatorGenericTitle,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: FontSize.style16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 16,
),
Text(
title ?? l10n.exceptionIndicatorGenericMessage,
textAlign: TextAlign.center,
),
if (onTryAgain != null)
const SizedBox(
height: Spacing.xxxLarge,
),
if (onTryAgain != null)
ExpandedElevatedButton(
onTap: onTryAgain,
icon: const Icon(
Icons.refresh,
),
label: l10n.exceptionIndicatorTryAgainButton,
),
],
),
),
);
}
}

View File

@ -1,22 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class GenericErrorSnackBar extends SnackBar {
const GenericErrorSnackBar({Key? key})
: super(
key: key,
content: const _GenericErrorSnackBarMessage(),
);
}
class _GenericErrorSnackBarMessage extends StatelessWidget {
const _GenericErrorSnackBarMessage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final l10n = ComponentLibraryLocalizations.of(context);
return Text(
l10n.genericErrorSnackbarMessage,
);
}
}

View File

@ -1,24 +0,0 @@
import 'package:flutter/material.dart';
class InProgressTextButton extends StatelessWidget {
const InProgressTextButton({
required this.label,
Key? key,
}) : super(key: key);
final String label;
@override
Widget build(BuildContext context) {
return TextButton.icon(
icon: Transform.scale(
scale: 0.5,
child: const CircularProgressIndicator(),
),
label: Text(
label,
),
onPressed: null,
);
}
}

View File

@ -0,0 +1,128 @@
import 'dart:ui';
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'error_message_builder.dart';
class InputField<T> extends StatefulWidget {
final String? label;
final String placeholder;
final Widget? suffixIcon;
final Widget? suffix;
final Widget? prefix;
final Widget? prefixIcon;
final String? errorMessage;
final bool obscureText;
final TextInputType textInputType;
final List<TextInputFormatter>? inputFormatters;
final bool isDisabled;
final bool isTouched;
final bool isError;
const InputField({
Key? key,
required this.placeholder,
this.label,
this.suffixIcon,
this.suffix,
this.prefix,
this.prefixIcon,
this.obscureText = false,
this.textInputType = TextInputType.text,
this.inputFormatters = const [],
this.errorMessage,
required this.isDisabled,
required this.isTouched,
required this.isError,
}) : super(key: key);
@override
State<InputField> createState() => _InputFieldState();
}
class _InputFieldState extends State<InputField> {
bool _hasFocus = false;
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
if (widget.label != null && widget.label?.isEmpty == true) ...[
Text(
widget.label!,
style: theme.textStyle.copyWith(fontSize: FontSize.style14),
),
],
Focus(
onFocusChange: (value) {
setState(() => _hasFocus = value);
},
child: Container(
height: 52,
decoration: BoxDecoration(
border: Border.all(
color:
_hasFocus ? theme.successBorderColor : Colors.transparent,
width: 3,
),
borderRadius: BorderRadius.circular(8.0),
),
child: TextField(
inputFormatters: widget.inputFormatters,
keyboardType: widget.textInputType,
obscureText: widget.obscureText,
selectionHeightStyle: BoxHeightStyle.strut,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
horizontal: 9.5,
vertical: 10,
),
counterText: '',
fillColor: widget.isDisabled
? const Color(0xffededed)
: Colors.transparent,
filled: true,
prefix: widget.prefix,
prefixIcon: widget.prefixIcon,
suffix: widget.suffix,
suffixIcon: widget.suffixIcon,
errorStyle: theme.textStyle.copyWith(
fontSize: 0,
),
prefixIconConstraints: const BoxConstraints(
minHeight: 24,
minWidth: 40,
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(color: theme.primaryBorderColor),
),
label: Text(
widget.placeholder,
style: theme.textStyle.copyWith(
fontSize: FontSize.style14,
color: widget.isTouched && widget.isError
? theme.dangerMainColor
: theme.neutral70Color,
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
),
style: theme.textStyle.copyWith(fontSize: FontSize.style14),
),
),
),
ErrorMessageBuilder(
inputLabel: widget.label ?? '',
messageError: widget.errorMessage ?? '',
)
],
);
}
}

View File

@ -1,50 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class RoundedChoiceChip extends StatelessWidget {
const RoundedChoiceChip({
required this.label,
required this.isSelected,
this.avatar,
this.labelColor,
this.selectedLabelColor,
this.backgroundColor,
this.selectedBackgroundColor,
this.onSelected,
Key? key,
}) : super(key: key);
final String label;
final Widget? avatar;
final ValueChanged<bool>? onSelected;
final Color? labelColor;
final Color? selectedLabelColor;
final Color? backgroundColor;
final Color? selectedBackgroundColor;
final bool isSelected;
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return ChoiceChip(
shape: const StadiumBorder(
side: BorderSide(),
),
avatar: avatar,
label: Text(
label,
style: TextStyle(
color: isSelected
? (selectedLabelColor ?? theme.primaryMainColor)
: (labelColor ?? theme.primarySurfaceColor),
),
),
onSelected: onSelected,
selected: isSelected,
backgroundColor:
(backgroundColor ?? theme.primaryMainColor),
selectedColor: (selectedBackgroundColor ??
theme.primarySurfaceColor),
);
}
}

View File

@ -1,35 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:component_library/src/theme/spacing.dart';
import 'package:flutter/material.dart';
class RowAppBar extends StatelessWidget implements PreferredSizeWidget {
const RowAppBar({
Key? key,
this.children = const [],
}) : super(key: key);
final List<Widget> children;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.only(
top: Spacing.small,
left: Spacing.small,
right: Spacing.small,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BackButton(),
...children,
],
),
),
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

View File

@ -1,29 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class SearchBar extends StatelessWidget {
const SearchBar({
this.controller,
this.onChanged,
Key? key,
}) : super(key: key);
final TextEditingController? controller;
final ValueChanged<String>? onChanged;
@override
Widget build(BuildContext context) {
final l10n = ComponentLibraryLocalizations.of(context);
return TextField(
controller: controller,
decoration: InputDecoration(
suffixIcon: const Icon(
Icons.search,
),
hintText: l10n.searchBarHintText,
labelText: l10n.searchBarLabelText,
),
onChanged: onChanged,
);
}
}

View File

@ -1,23 +0,0 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class ShareIconButton extends StatelessWidget {
const ShareIconButton({
Key? key,
this.onTap,
}) : super(key: key);
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
final l10n = ComponentLibraryLocalizations.of(context);
return IconButton(
onPressed: onTap,
tooltip: l10n.shareIconButtonTooltip,
icon: const Icon(
Icons.share,
),
);
}
}

View File

@ -1,24 +0,0 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
class ShrinkableText extends StatelessWidget {
const ShrinkableText(
this.data, {
this.style,
this.textAlign = TextAlign.center,
Key? key,
}) : super(key: key);
final String data;
final TextStyle? style;
final TextAlign? textAlign;
@override
Widget build(BuildContext context) {
return AutoSizeText(
data,
style: style,
textAlign: textAlign,
);
}
}

View File

@ -1,41 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// Useful for changing the status bar color when the screen doesn't have an
// AppBar. For screens with AppBars, please use the [] property.
class StyledStatusBar extends StatelessWidget {
const StyledStatusBar._({
required this.child,
required this.style,
Key? key,
}) : super(key: key);
const StyledStatusBar.light({
required Widget child,
Key? key,
}) : this._(
child: child,
style: SystemUiOverlayStyle.light,
key: key,
);
const StyledStatusBar.dark({
required Widget child,
Key? key,
}) : this._(
child: child,
style: SystemUiOverlayStyle.dark,
key: key,
);
final Widget child;
final SystemUiOverlayStyle style;
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: style,
child: child,
);
}
}

View File

@ -117,6 +117,60 @@ class LightGolekThemeData extends GolekThemeData {
brightness: Brightness.light,
primarySwatch: Colors.black.toMaterialColor(),
dividerTheme: _dividerThemeData,
backgroundColor: neutral10Color,
appBarTheme: const AppBarTheme(
backgroundColor: Colors.transparent,
elevation: 0,
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: primaryMainColor,
side: const BorderSide(
color: Colors.transparent,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
),
),
primaryColor: primaryMainColor,
inputDecorationTheme: InputDecorationTheme(
errorStyle: const TextStyle(fontSize: 0, height: 1),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(color: neutral50Color),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(color: neutral50Color),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(color: neutral50Color),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(
color: primaryBorderColor,
width: 2,
),
),
hintStyle: textStyle.copyWith(
fontSize: FontSize.style14,
color: neutral70Color,
),
floatingLabelBehavior: FloatingLabelBehavior.never,
),
colorScheme: ColorScheme.light(
primary: primaryMainColor, // header background color
onSurface: secondaryMainColor, // body text color
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: primaryMainColor, // button text color
),
),
);
@override
@ -219,13 +273,13 @@ class LightGolekThemeData extends GolekThemeData {
Color get successPressedColor => const Color(0xff18D48C);
@override
Color get successSurfaceColor => const Color(0xffECFFF8);
Color get successSurfaceColor => const Color(0xffECFFF8);
@override
Color get tertiaryBorderColor => const Color(0xffDCE6F6);
Color get tertiaryBorderColor => const Color(0xffDCE6F6);
@override
Color get tertiaryFocusColor => const Color.fromRGBO(198, 207, 221, 0.2);
Color get tertiaryFocusColor => const Color.fromRGBO(198, 207, 221, 0.2);
@override
Color get tertiaryHoverColor => const Color(0xffB0B8C5);
@ -237,22 +291,22 @@ class LightGolekThemeData extends GolekThemeData {
Color get tertiaryPressedColor => const Color(0xff9AA1AC);
@override
Color get tertiarySurfaceColor =>const Color(0xffF5F5F5);
Color get tertiarySurfaceColor => const Color(0xffF5F5F5);
@override
Color get warningBorderColor => const Color(0xffFFF9CF);
@override
Color get warningHoverColor => const Color(0xffFEE31A);
Color get warningHoverColor => const Color(0xffFEE31A);
@override
Color get warningMainColor => const Color(0xffFFEE6E);
@override
Color get warningPressedColor => const Color(0xffCBB511);
Color get warningPressedColor => const Color(0xffCBB511);
@override
Color get warningSurfaceColor => const Color(0xffFFFCE2);
Color get warningSurfaceColor => const Color(0xffFFFCE2);
}
class DarkGolekThemeData extends GolekThemeData {

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,7 +1,6 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
import 'package:landing_menu/src/widgets/landing_app_bar.dart';
import 'landing_page/landing_app_bar.dart';
class LandingPage extends StatefulWidget {
const LandingPage({Key? key}) : super(key: key);
@ -57,7 +56,8 @@ class _LandingPageState extends State<LandingPage> {
mainAxisAlignment: MainAxisAlignment.end,
children: [
Image.asset(
'assets/images/truckershipper.png',
'assets/trucker_shipper.png',
package: 'features/landing_menu',
width: 300,
height: 200,
),
@ -94,7 +94,7 @@ class _LandingPageState extends State<LandingPage> {
onClickInfo: () => {},
label: 'Cari Truk',
description: 'Pengirim Muatan',
assets: 'assets/images/box_shipper.png',
assets: 'assets/box_shipper.png',
onTap: () {},
),
const SizedBox(width: 14),
@ -102,7 +102,7 @@ class _LandingPageState extends State<LandingPage> {
onClickInfo: () => {},
label: 'Cari Muatan',
description: 'Penyedia Angkutan',
assets: 'assets/images/truk_trucker.png',
assets: 'assets/truk_trucker.png',
onTap: () async {},
),
],
@ -173,7 +173,7 @@ class CardProduct extends StatelessWidget {
),
const SizedBox(height: 8),
Image(
image: AssetImage(assets),
image: AssetImage(assets, package: 'features/landing_menu'),
width: 131,
height: 100,
fit: BoxFit.contain,

View File

@ -11,6 +11,7 @@ class LandingAppBar extends StatelessWidget with PreferredSizeWidget {
final theme = GolekTheme.of(context);
return AppBar(
elevation: 0,
backgroundColor: theme.primaryMainColor,
actions: [
CompositedTransformTarget(

View File

@ -2,7 +2,7 @@
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// gestures. You can also use WidgetTester to find child landing_page in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter_test/flutter_test.dart';

View File

@ -2,7 +2,7 @@
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// gestures. You can also use WidgetTester to find child landing_page in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter_test/flutter_test.dart';

View File

@ -34,3 +34,5 @@ dev_dependencies:
build_runner: ^2.3.2
flutter:
uses-material-design: true
assets:
- packages/features/landing_menu/assets/