From 2a543782e2fb8403b80e4438f599aba84b4a2f44 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Tue, 29 Apr 2025 14:09:13 +0900 Subject: [PATCH 1/6] chore: remove unnecessary blank lines in launch configuration --- .vscode/launch.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index a1c0c45a..7b070fdb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,7 +4,6 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { "name": "on_time_front", "request": "launch", @@ -14,7 +13,6 @@ ".env/debug.env", "--web-port", "58102" - ] }, { From aeef3cbbeac421ee189a8d0b0d04c41951767162 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Tue, 29 Apr 2025 14:09:55 +0900 Subject: [PATCH 2/6] refactor: enhance dialog theme with custom styles and remove unused theme definition --- lib/presentation/shared/theme/theme.dart | 28 ++++++++---------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/presentation/shared/theme/theme.dart b/lib/presentation/shared/theme/theme.dart index bca98dda..f74d8dd1 100644 --- a/lib/presentation/shared/theme/theme.dart +++ b/lib/presentation/shared/theme/theme.dart @@ -124,6 +124,15 @@ ThemeData themeData = ThemeData( shape: WidgetStatePropertyAll( RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), )), + dialogTheme: DialogTheme( + backgroundColor: colorScheme.surface, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + titleTextStyle: + textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w600), + contentTextStyle: textTheme.bodyMedium, + ), extensions: >[ TileStyle( backgroundColor: colorScheme.surfaceContainerLow, @@ -143,22 +152,3 @@ ThemeData themeData = ThemeData( ), ], ); - -final ThemeData appTheme = ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), - dialogTheme: DialogTheme( - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - titleTextStyle: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - contentTextStyle: TextStyle( - fontSize: 13, - color: Colors.black, - ), - ), -); From 7bbdaa96d6ef3eafb65ba23c5374081d22979660 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Fri, 2 May 2025 07:01:51 +0900 Subject: [PATCH 3/6] feat: implement CustomAlertDialog component and remove ModalComponent --- .../components/custom_alert_dialog.dart | 421 ++++++++++++++++++ .../shared/components/modal_component.dart | 33 -- 2 files changed, 421 insertions(+), 33 deletions(-) create mode 100644 lib/presentation/shared/components/custom_alert_dialog.dart delete mode 100644 lib/presentation/shared/components/modal_component.dart diff --git a/lib/presentation/shared/components/custom_alert_dialog.dart b/lib/presentation/shared/components/custom_alert_dialog.dart new file mode 100644 index 00000000..4f956fec --- /dev/null +++ b/lib/presentation/shared/components/custom_alert_dialog.dart @@ -0,0 +1,421 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +class CustomAlertDialog extends StatelessWidget { + const CustomAlertDialog({ + super.key, + this.title, + this.titleTextStyle, + this.content, + this.contentTextStyle, + this.actions, + this.actionsAlignment, + this.actionsOverflowAlignment, + this.actionsOverflowDirection, + this.actionsOverflowButtonSpacing, + this.buttonPadding, + this.backgroundColor, + this.elevation, + this.shadowColor, + this.surfaceTintColor, + this.semanticLabel, + this.innerPadding, + this.insetPadding, + this.clipBehavior, + this.shape, + this.alignment, + this.scrollable = false, + this.titleContentSpacing, + this.contentActionsSpacing, + }) : _defaultTitleTextAlign = TextAlign.start, + _defualtContentTextAlign = TextAlign.start; + + /// The (optional) title of the dialog is displayed in a large font at the top + /// of the dialog, below the (optional) [icon]. + /// + /// Typically a [Text] widget. + final Widget? title; + + /// Style for the text in the [title] of this [CustomAlertDialog]. + /// + /// If null, [DialogThemeData.titleTextStyle] is used. If that's null, defaults to + /// [TextTheme.headlineSmall] of [ThemeData.textTheme] if + /// [ThemeData.useMaterial3] is true, [TextTheme.titleLarge] otherwise. + final TextStyle? titleTextStyle; + + /// The (optional) content of the dialog is displayed in the center of the + /// dialog in a lighter font. + /// + /// Typically this is a [SingleChildScrollView] that contains the dialog's + /// message. As noted in the [CustomAlertDialog] documentation, it's important + /// to use a [SingleChildScrollView] if there's any risk that the content + /// will not fit, as the contents will otherwise overflow the dialog. + /// + /// The [content] must support reporting its intrinsic dimensions. In + /// particular, [ListView], [GridView], and [CustomScrollView] cannot be used + /// here unless they are first wrapped in a widget that itself can report + /// intrinsic dimensions, such as a [SizedBox]. + final Widget? content; + + /// Style for the text in the [content] of this [CustomAlertDialog]. + /// + /// If null, [DialogThemeData.contentTextStyle] is used. If that's null, defaults + /// to [TextTheme.bodyMedium] of [ThemeData.textTheme] + final TextStyle? contentTextStyle; + + /// The (optional) set of actions that are displayed at the bottom of the + /// dialog with an [OverflowBar]. + /// + /// Typically this is a list of [TextButton] widgets. It is recommended to + /// set the [Text.textAlign] to [TextAlign.end] for the [Text] within the + /// [TextButton], so that buttons whose labels wrap to an extra line align + /// with the overall [OverflowBar]'s alignment within the dialog. + /// + /// If the [title] is not null but the [content] _is_ null, then an extra 20 + /// pixels of padding is added above the [OverflowBar] to separate the [title] + /// from the [actions]. + final List? actions; + + /// Defines the horizontal layout of the [actions] according to the same + /// rules as for [Row.mainAxisAlignment]. + /// + /// This parameter is passed along to the dialog's [OverflowBar]. + /// + /// If this parameter is null (the default) then [MainAxisAlignment.end] + /// is used. + final MainAxisAlignment? actionsAlignment; + + /// The horizontal alignment of [actions] within the vertical + /// "overflow" layout. + /// + /// If the dialog's [actions] do not fit into a single row, then they + /// are arranged in a column. This parameter controls the horizontal + /// alignment of widgets in the case of an overflow. + /// + /// If this parameter is null (the default) then [OverflowBarAlignment.end] + /// is used. + /// + /// See also: + /// + /// * [OverflowBar], which [actions] configures to lay itself out. + final OverflowBarAlignment? actionsOverflowAlignment; + + /// The vertical direction of [actions] if the children overflow + /// horizontally. + /// + /// If the dialog's [actions] do not fit into a single row, then they + /// are arranged in a column. The first action is at the top of the + /// column if this property is set to [VerticalDirection.down], since it + /// "starts" at the top and "ends" at the bottom. On the other hand, + /// the first action will be at the bottom of the column if this + /// property is set to [VerticalDirection.up], since it "starts" at the + /// bottom and "ends" at the top. + /// + /// See also: + /// + /// * [OverflowBar], which [actions] configures to lay itself out. + final VerticalDirection? actionsOverflowDirection; + + /// The spacing between [actions] when the [OverflowBar] switches to a column + /// layout because the actions don't fit horizontally. + /// + /// If the widgets in [actions] do not fit into a single row, they are + /// arranged into a column. This parameter provides additional vertical space + /// between buttons when it does overflow. + /// + /// The button spacing may appear to be more than the value provided. This is + /// because most buttons adhere to the [MaterialTapTargetSize] of 48px. So, + /// even though a button might visually be 36px in height, it might still take + /// up to 48px vertically. + /// + /// If null then no spacing will be added in between buttons in an overflow + /// state. + final double? actionsOverflowButtonSpacing; + + /// The padding that surrounds each button in [actions]. + /// + /// If this property is null, then it will default to + /// 8.0 logical pixels on the left and right. + final EdgeInsetsGeometry? buttonPadding; + + /// {@macro flutter.material.dialog.backgroundColor} + final Color? backgroundColor; + + /// {@macro flutter.material.dialog.elevation} + final double? elevation; + + /// {@macro flutter.material.dialog.shadowColor} + final Color? shadowColor; + + /// {@macro flutter.material.dialog.surfaceTintColor} + final Color? surfaceTintColor; + + /// The semantic label of the dialog used by accessibility frameworks to + /// announce screen transitions when the dialog is opened and closed. + /// + /// In iOS, if this label is not provided, a semantic label will be inferred + /// from the [title] if it is not null. + /// + /// In Android, if this label is not provided, the dialog will use the + /// [MaterialLocalizations.alertDialogLabel] as its label. + /// + /// See also: + /// + /// * [SemanticsConfiguration.namesRoute], for a description of how this + /// value is used. + final String? semanticLabel; + + /// The padding that surrounds the dialog. + /// + /// This is different from [insetPadding], which defines the padding + /// between the dialog and the screen. + /// + /// If this property is null, then it will default to + /// 20.0 logical pixels on the left and right and 18.0 logical pixels on + /// the top and bottom. + final EdgeInsets? innerPadding; + + /// {@macro flutter.material.dialog.insetPadding} + final EdgeInsets? insetPadding; + + /// {@macro flutter.material.dialog.clipBehavior} + final Clip? clipBehavior; + + /// {@macro flutter.material.dialog.shape} + final ShapeBorder? shape; + + /// {@macro flutter.material.dialog.alignment} + final AlignmentGeometry? alignment; + + /// Determines whether the [title] and [content] widgets are wrapped in a + /// scrollable. + /// + /// This configuration is used when the [title] and [content] are expected + /// to overflow. Both [title] and [content] are wrapped in a scroll view, + /// allowing all overflowed content to be visible while still showing the + /// button bar. + final bool scrollable; + + /// The spacing between title and content. + /// + /// If null, then it will default to 8.0 logical pixels. + /// If 0.0, then no spacing will be added in between title and content. + final double? titleContentSpacing; + + /// The spacing between content and actions. + /// + /// If null, then it will default to 18.0 logical pixels. + /// If 0.0, then no spacing will be added in between content and actions. + final double? contentActionsSpacing; + + final TextAlign _defaultTitleTextAlign; + final TextAlign _defualtContentTextAlign; + + const CustomAlertDialog.error({ + super.key, + this.title, + this.titleTextStyle, + this.content, + this.contentTextStyle, + this.actions, + this.actionsAlignment, + this.actionsOverflowAlignment, + this.actionsOverflowDirection, + this.actionsOverflowButtonSpacing, + this.buttonPadding, + this.backgroundColor, + this.elevation, + this.shadowColor, + this.surfaceTintColor, + this.semanticLabel, + this.innerPadding, + this.insetPadding, + this.clipBehavior, + this.shape, + this.alignment = Alignment.center, + this.scrollable = false, + this.titleContentSpacing = 6.0, + this.contentActionsSpacing = 16.0, + }) : _defaultTitleTextAlign = TextAlign.center, + _defualtContentTextAlign = TextAlign.center; + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); + final ThemeData theme = Theme.of(context); + + final DialogThemeData dialogTheme = DialogTheme.of(context); + final DialogThemeData defaults = _DialogDefaults(context); + + String? label = semanticLabel; + switch (theme.platform) { + case TargetPlatform.iOS: + case TargetPlatform.macOS: + break; + case TargetPlatform.android: + case TargetPlatform.fuchsia: + case TargetPlatform.linux: + case TargetPlatform.windows: + label ??= MaterialLocalizations.of(context).alertDialogLabel; + } + + final double paddingScaleFactor = + _scalePadding(MediaQuery.textScalerOf(context).scale(14.0) / 14.0); + + Widget? titleWidget; + Widget? contentWidget; + Widget? actionsWidget; + + if (title != null) { + titleWidget = DefaultTextStyle( + style: titleTextStyle ?? + dialogTheme.titleTextStyle ?? + defaults.titleTextStyle!, + textAlign: _defaultTitleTextAlign, + child: Semantics( + namesRoute: label == null && theme.platform != TargetPlatform.iOS, + container: true, + child: title, + ), + ); + } + + if (content != null) { + contentWidget = DefaultTextStyle( + style: contentTextStyle ?? + dialogTheme.contentTextStyle ?? + defaults.contentTextStyle!, + textAlign: _defualtContentTextAlign, + child: Semantics( + container: true, + explicitChildNodes: true, + child: content, + ), + ); + } + + if (actions != null) { + final double spacing = (buttonPadding?.horizontal ?? 16) / 2; + actionsWidget = OverflowBar( + alignment: actionsAlignment ?? MainAxisAlignment.end, + spacing: spacing, + overflowAlignment: actionsOverflowAlignment ?? OverflowBarAlignment.end, + overflowDirection: actionsOverflowDirection ?? VerticalDirection.down, + overflowSpacing: actionsOverflowButtonSpacing ?? 0, + children: actions!, + ); + } + + List columnChildren = []; + final SizedBox defaultTitleContentSpacing = const SizedBox(height: 8.0); + final SizedBox defaultContentActionsSpacing = const SizedBox(height: 18.0); + final SizedBox effectiveTitleContentSpacing = titleContentSpacing == null + ? defaultTitleContentSpacing + : SizedBox( + height: titleContentSpacing, + ); + final SizedBox effectiveContentActionsSpacing = + contentActionsSpacing == null + ? defaultContentActionsSpacing + : SizedBox( + height: contentActionsSpacing, + ); + if (title != null) columnChildren.add(titleWidget!); + if (title != null && content != null) { + columnChildren.add(effectiveTitleContentSpacing); + } + if (content != null) columnChildren.add(contentWidget!); + if ((title != null || content != null) && actions != null) { + columnChildren.add( + effectiveContentActionsSpacing, + ); + } + if (actions != null) columnChildren.add(actionsWidget!); + + final EdgeInsets defaultInnerPadding = EdgeInsets.only( + left: 20.0, + top: 20.0, + right: 18.0, + bottom: 18.0, + ); + final EdgeInsets effectiveInnerPadding = + innerPadding ?? defaultInnerPadding; + Widget dialogChild = IntrinsicWidth( + child: Padding( + padding: effectiveInnerPadding * paddingScaleFactor, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: columnChildren, + ), + ), + ); + + if (label != null) { + dialogChild = Semantics( + scopesRoute: true, + explicitChildNodes: true, + namesRoute: true, + label: label, + child: dialogChild, + ); + } + + return Dialog( + backgroundColor: backgroundColor, + elevation: elevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, + insetPadding: insetPadding, + clipBehavior: clipBehavior, + shape: shape, + alignment: alignment, + child: dialogChild, + ); + } +} + +double _scalePadding(double textScaleFactor) { + final double clampedTextScaleFactor = clampDouble(textScaleFactor, 1.0, 2.0); + // The final padding scale factor is clamped between 1/3 and 1. For example, + // a non-scaled padding of 24 will produce a padding between 24 and 8. + return lerpDouble(1.0, 1.0 / 3.0, clampedTextScaleFactor - 1.0)!; +} + +class _DialogDefaults extends DialogThemeData { + _DialogDefaults(this.context) + : super( + alignment: Alignment.center, + elevation: 6.0, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(28.0))), + clipBehavior: Clip.none, + ); + + final BuildContext context; + late final ColorScheme _colors = Theme.of(context).colorScheme; + late final TextTheme _textTheme = Theme.of(context).textTheme; + + @override + Color? get iconColor => _colors.secondary; + + @override + Color? get backgroundColor => _colors.surfaceContainerHigh; + + @override + Color? get shadowColor => Colors.transparent; + + @override + Color? get surfaceTintColor => Colors.transparent; + + @override + TextStyle? get titleTextStyle => _textTheme.headlineSmall; + + @override + TextStyle? get contentTextStyle => _textTheme.bodyMedium; + + @override + EdgeInsetsGeometry? get actionsPadding => + const EdgeInsets.only(left: 0.0, right: 0.0, bottom: 0.0); +} diff --git a/lib/presentation/shared/components/modal_component.dart b/lib/presentation/shared/components/modal_component.dart deleted file mode 100644 index 65609691..00000000 --- a/lib/presentation/shared/components/modal_component.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'dart:ui'; -import 'package:flutter/material.dart'; -import 'package:on_time_front/presentation/shared/theme/theme.dart'; - -class ModalComponent extends StatelessWidget { - final Widget title; - final Widget content; - final List actions; - - const ModalComponent({ - super.key, - required this.title, - required this.content, - required this.actions, - }); - - @override - Widget build(BuildContext context) { - return BackdropFilter( - filter: ImageFilter.blur(sigmaX: 0, sigmaY: 0), - child: AlertDialog( - shape: appTheme.dialogTheme.shape, - backgroundColor: appTheme.dialogTheme.backgroundColor, - title: title, - titleTextStyle: appTheme.dialogTheme.titleTextStyle, - content: content, - contentTextStyle: appTheme.dialogTheme.contentTextStyle, - actions: actions, - actionsAlignment: MainAxisAlignment.spaceEvenly, - ), - ); - } -} From 04029c38c06b16148a5f90974f7a4b8eaf128691 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Fri, 2 May 2025 07:02:45 +0900 Subject: [PATCH 4/6] refactor: remove unnecessary padding from background container in WidgetbookApp --- widgetbook/lib/main.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/widgetbook/lib/main.dart b/widgetbook/lib/main.dart index 6ca071cf..e1a4f897 100644 --- a/widgetbook/lib/main.dart +++ b/widgetbook/lib/main.dart @@ -52,10 +52,7 @@ class WidgetbookApp extends StatelessWidget { height: double.infinity, width: double.infinity, color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: child, - ), + child: child, ); }, ), From cce037c6ad0dae598cd057788809df947631e4dd Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Fri, 2 May 2025 07:02:54 +0900 Subject: [PATCH 5/6] refactor: replace ModalComponent with CustomAlertDialog in ScheduleStartScreen --- .../alarm/screens/schedule_start_screen.dart | 128 +++++++++--------- 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/lib/presentation/alarm/screens/schedule_start_screen.dart b/lib/presentation/alarm/screens/schedule_start_screen.dart index f999ed6a..b786dfdd 100644 --- a/lib/presentation/alarm/screens/schedule_start_screen.dart +++ b/lib/presentation/alarm/screens/schedule_start_screen.dart @@ -5,7 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:on_time_front/domain/entities/schedule_entity.dart'; import 'package:on_time_front/presentation/shared/components/button.dart'; import 'package:on_time_front/presentation/shared/components/modal_button.dart'; -import 'package:on_time_front/presentation/shared/components/modal_component.dart'; +import 'package:on_time_front/presentation/shared/components/custom_alert_dialog.dart'; class ScheduleStartScreen extends StatefulWidget { final ScheduleEntity schedule; @@ -32,76 +32,78 @@ class _ScheduleStartScreenState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: Stack( - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 60), - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - widget.schedule.scheduleName, - style: const TextStyle( - fontSize: 40, - fontWeight: FontWeight.bold, - color: Color(0xff5C79FB), + return SafeArea( + child: Scaffold( + body: Stack( + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 60), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.schedule.scheduleName, + style: const TextStyle( + fontSize: 40, + fontWeight: FontWeight.bold, + color: Color(0xff5C79FB), + ), ), - ), - const SizedBox(height: 8), - Text( - widget.schedule.place.placeName, - style: const TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, + const SizedBox(height: 8), + Text( + widget.schedule.place.placeName, + style: const TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 15), - Text( - '지금 준비 시작 안하면 늦어요!', - style: const TextStyle( - fontSize: 15, + const SizedBox(height: 15), + Text( + '지금 준비 시작 안하면 늦어요!', + style: const TextStyle( + fontSize: 15, + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, - ), - Padding( - padding: const EdgeInsets.only(top: 50), - child: SvgPicture.asset( - 'characters/character.svg', - package: 'assets', - width: 204, - height: 269, + Padding( + padding: const EdgeInsets.only(top: 50), + child: SvgPicture.asset( + 'characters/character.svg', + package: 'assets', + width: 204, + height: 269, + ), ), - ), - ], + ], + ), ), ), - ), - const Spacer(), - Padding( - padding: const EdgeInsets.only(bottom: 30), - child: Button( - text: '준비 시작', - onPressed: () async { - context.go('/alarmScreen', extra: widget.schedule); - }, + const Spacer(), + Padding( + padding: const EdgeInsets.only(bottom: 30), + child: Button( + text: '준비 시작', + onPressed: () async { + context.go('/alarmScreen', extra: widget.schedule); + }, + ), ), + ], + ), + Positioned( + top: 10, + right: 10, + child: IconButton( + icon: const Icon(Icons.close), + onPressed: () => _showModal(context), ), - ], - ), - Positioned( - top: 10, - right: 10, - child: IconButton( - icon: const Icon(Icons.close), - onPressed: () => _showModal(context), ), - ), - ], + ], + ), ), ); } @@ -110,7 +112,7 @@ class _ScheduleStartScreenState extends State { class _ScheduleStartScreenModal extends StatelessWidget { @override Widget build(BuildContext context) { - return ModalComponent( + return CustomAlertDialog( title: const Text( '정말 나가시겠어요?', ), From d9818ec1f0f089fb725d441873b8f17ab90e01ff Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Fri, 2 May 2025 07:02:58 +0900 Subject: [PATCH 6/6] feat: add CustomAlertDialog component and remove ModalComponent --- widgetbook/lib/custom_alert_dialog.dart | 100 ++++++++++++++++++++++++ widgetbook/lib/modal_component.dart | 56 ------------- 2 files changed, 100 insertions(+), 56 deletions(-) create mode 100644 widgetbook/lib/custom_alert_dialog.dart delete mode 100644 widgetbook/lib/modal_component.dart diff --git a/widgetbook/lib/custom_alert_dialog.dart b/widgetbook/lib/custom_alert_dialog.dart new file mode 100644 index 00000000..07250d36 --- /dev/null +++ b/widgetbook/lib/custom_alert_dialog.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/presentation/shared/components/modal_button.dart'; +import 'package:on_time_front/presentation/shared/components/custom_alert_dialog.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; +import 'package:on_time_front/presentation/shared/theme/theme.dart'; + +@widgetbook.UseCase( + name: 'default', + type: CustomAlertDialog, +) +Widget customAlertDialog(BuildContext context) { + final titleText = context.knobs.string( + label: 'Dialog Title', + initialValue: '정말 나가시겠어요?', + ); + + final contentText = context.knobs.string( + label: 'Dilog Content', + initialValue: '이 화면을 나가면\n함께 약속을 준비할 수 없게 돼요', + ); + + return Container( + height: double.infinity, + width: double.infinity, + color: Colors.black.withValues( + alpha: 0.4, + ), + child: CustomAlertDialog( + title: Text( + titleText, + ), + content: Text( + contentText, + ), + actionsAlignment: MainAxisAlignment.spaceBetween, + alignment: Alignment.center, + actions: [ + FilledButton( + onPressed: () {}, + child: const Text( + '나갈래', + ), + ), + FilledButton( + onPressed: () {}, + child: const Text( + '있을래', + ), + ) + ], + ), + ); +} + +@widgetbook.UseCase( + name: 'Error', + type: CustomAlertDialog, +) +Widget errorCusmtomAlertDialog(BuildContext context) { + final titleText = context.knobs.string( + label: 'Dialog Title', + initialValue: '다 챙기셨나요?', + ); + + final contentText = context.knobs.string( + label: 'Dolog Content', + initialValue: '아직 챙기지 않은 것들이 있어요.', + ); + + return Container( + height: double.infinity, + width: double.infinity, + color: Colors.black.withValues( + alpha: 0.4, + ), + child: CustomAlertDialog.error( + title: Text( + titleText, + ), + content: Text( + contentText, + ), + actionsAlignment: MainAxisAlignment.spaceBetween, + alignment: Alignment.center, + actions: [ + FilledButton( + onPressed: () {}, + style: FilledButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.error, + foregroundColor: Theme.of(context).colorScheme.onError, + ), + child: const Text( + '확인', + ), + ), + ], + ), + ); +} diff --git a/widgetbook/lib/modal_component.dart b/widgetbook/lib/modal_component.dart deleted file mode 100644 index 41e0d2e3..00000000 --- a/widgetbook/lib/modal_component.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:on_time_front/presentation/shared/components/modal_component.dart'; -import 'package:on_time_front/presentation/shared/components/modal_button.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; -import 'package:on_time_front/presentation/shared/theme/theme.dart'; - -@widgetbook.UseCase( - name: 'Dynamic Buttons', - type: ModalComponent, -) -Widget useCaseModalComponent(BuildContext context) { - final titleText = context.knobs.string( - label: 'Modal Title', - initialValue: 'Modal Title', - ); - - final contentText = context.knobs.string( - label: 'Modal Detail', - initialValue: 'Modal Detail', - ); - - final showFirstButton = context.knobs.boolean( - label: 'First Button', - initialValue: true, - ); - - final firstButtonText = context.knobs.string( - label: 'Button Text', - initialValue: 'Button', - ); - - final List buttons = []; - - if (showFirstButton) { - buttons.add( - ModalButton( - onPressed: () {}, - text: firstButtonText, - color: colorScheme.surfaceContainer, - textColor: colorScheme.outline, - ), - ); - } - - return Scaffold( - backgroundColor: const Color.fromARGB(255, 243, 241, 241), - body: Center( - child: ModalComponent( - title: Text(titleText), - content: Text(contentText), - actions: buttons, - ), - ), - ); -}