@@ -2,21 +2,252 @@ import 'package:auto_route/auto_route.dart';
22import 'package:flutter/foundation.dart' ;
33
44import 'package:flutter/material.dart' ;
5+ import 'package:flutter_sticky_header/flutter_sticky_header.dart' ;
6+ import 'package:flutter_template/presentation/resources/app_colors.dart' ;
7+ import 'package:flutter_template/presentation/resources/app_ui_constants.dart' ;
58import 'package:flutter_template/presentation/routes/router.gr.dart' ;
9+ import 'package:flutter_template/presentation/widgets/app_bar/top_app_bar.dart' ;
10+ import 'package:flutter_template/presentation/widgets/button/app_button.dart' ;
11+ import 'package:flutter_template/presentation/widgets/spacers/safe_area_spacer.dart' ;
12+ import 'package:flutter_template/presentation/widgets/text/app_text.dart' ;
13+ import 'package:flutter_template/presentation/widgets/utilities/app_screen_config.dart' ;
614
15+ /// A playground screen designed for showcasing reusable widgets.
16+ ///
17+ /// This screen is intended for presenting and testing reusable widgets within
18+ /// the context of a Flutter application.
19+ ///
20+ /// If you need to extract some small widgets only for this playground screen,
21+ /// consider using the private modifier for widget classes.
722@RoutePage ()
823class PlaygroundScreen extends StatelessWidget {
924 const PlaygroundScreen ({super .key});
1025
1126 @override
1227 Widget build (BuildContext context) {
13- return Scaffold (
14- appBar: AppBar (
15- title: const Text ('Playground' ),
28+ const verticalGap = SizedBox (height: 12 );
29+ const sliverGap = SliverToBoxAdapter (
30+ child: verticalGap,
31+ );
32+
33+ return AppScreenConfig (
34+ child: Scaffold (
35+ appBar: const TopAppBar (
36+ label: 'Playground' ,
37+ ),
38+ body: CustomScrollView (
39+ slivers: [
40+ _PlaygroundStickyHeader (
41+ label: 'Color Boxes' ,
42+ child: Wrap (
43+ children: [
44+ _PlaygroundColorBox (
45+ label: 'Primary' ,
46+ color: context.colors.primary,
47+ labelColor: context.colors.foregroundOnPrimary,
48+ ),
49+ _PlaygroundColorBox (
50+ label: 'Secondary' ,
51+ color: context.colors.secondary,
52+ labelColor: context.colors.foregroundOnSecondary,
53+ ),
54+ _PlaygroundColorBox (
55+ label: 'Background' ,
56+ color: context.colors.background,
57+ labelColor: context.colors.foregroundOnBackground,
58+ ),
59+ _PlaygroundColorBox (
60+ label: 'Danger' ,
61+ color: context.colors.danger,
62+ labelColor: context.colors.foregroundOnDanger,
63+ ),
64+ _PlaygroundColorBox (
65+ label: 'Outline' ,
66+ color: context.colors.outline,
67+ labelColor: context.colors.foregroundOnPrimary,
68+ ),
69+ _PlaygroundColorBox (
70+ label: 'Primary Variant' ,
71+ color: context.colors.primaryVariant,
72+ labelColor: context.colors.foregroundOnPrimary,
73+ ),
74+ _PlaygroundColorBox (
75+ label: 'Secondary Variant' ,
76+ color: context.colors.secondaryVariant,
77+ labelColor: context.colors.foregroundOnSecondary,
78+ ),
79+ _PlaygroundColorBox (
80+ label: 'Splash' ,
81+ color: context.colors.splashColor,
82+ labelColor: context.colors.foregroundOnBackground,
83+ ),
84+ ],
85+ ),
86+ ),
87+ sliverGap,
88+ _PlaygroundStickyHeader (
89+ label: 'Buttons' ,
90+ child: Column (
91+ children: [
92+ AppButton .primary (
93+ label: 'Primary Button' ,
94+ onPressed: () {},
95+ ),
96+ verticalGap,
97+ AppButton .secondary (
98+ label: 'Secondary Button' ,
99+ onPressed: () {},
100+ ),
101+ verticalGap,
102+ AppButton .outlined (
103+ label: 'Outlined Button' ,
104+ onPressed: () {},
105+ ),
106+ verticalGap,
107+ AppButton .destructive (
108+ label: 'Destructive Button' ,
109+ onPressed: () {},
110+ ),
111+ verticalGap,
112+ AppButton .text (
113+ label: 'Text Button' ,
114+ onPressed: () {},
115+ ),
116+ ],
117+ ),
118+ ),
119+ sliverGap,
120+ _PlaygroundStickyHeader (
121+ label: 'Small Buttons' ,
122+ child: Column (
123+ children: [
124+ Row (
125+ children: [
126+ Expanded (
127+ child: AppButton .primary (
128+ label: 'Small Primary Button' ,
129+ isSmall: true ,
130+ onPressed: () {},
131+ ),
132+ ),
133+ const SizedBox (width: 12 ),
134+ Expanded (
135+ child: AppButton .secondary (
136+ label: 'Small Secondary Button' ,
137+ isSmall: true ,
138+ onPressed: () {},
139+ ),
140+ ),
141+ ],
142+ ),
143+ ],
144+ ),
145+ ),
146+ sliverGap,
147+ _PlaygroundStickyHeader (
148+ label: 'Texts' ,
149+ child: Column (
150+ children: [
151+ AppText .header1 ('Header 1' ),
152+ verticalGap,
153+ AppText .header2 ('Header 2' ),
154+ verticalGap,
155+ AppText .header3 ('Header 3' ),
156+ verticalGap,
157+ AppText .bodySmall ('This is Body (small).' ),
158+ verticalGap,
159+ AppText .body ('This is Body (regular).' ),
160+ verticalGap,
161+ AppText .bodyLarge ('This is Body (large).' ),
162+ verticalGap,
163+ AppText .buttonLabel ('This is Button label.' ),
164+ verticalGap,
165+ AppText .underlineText ('This is underlined text.' ),
166+ verticalGap,
167+ AppText .custom (
168+ 'This is custom' ,
169+ fontWeight: FontWeight .w700,
170+ ),
171+ ],
172+ ),
173+ ),
174+ const SliverToBoxAdapter (
175+ child: SizedBox (
176+ height: 72 ,
177+ ),
178+ ),
179+ const SliverToBoxAdapter (
180+ child: SafeAreaSpacer (),
181+ ),
182+ ],
183+ ),
16184 ),
17- body: const SingleChildScrollView (
18- child: Column (
19- children: [],
185+ );
186+ }
187+ }
188+
189+ class _PlaygroundStickyHeader extends StatelessWidget {
190+ const _PlaygroundStickyHeader ({
191+ required this .label,
192+ required this .child,
193+ });
194+
195+ final String label;
196+ final Widget child;
197+
198+ @override
199+ Widget build (BuildContext context) {
200+ return SliverStickyHeader (
201+ header: ColoredBox (
202+ color: context.colors.background,
203+ child: Padding (
204+ padding: const EdgeInsets .symmetric (
205+ horizontal: 24.0 ,
206+ vertical: 12.0 ,
207+ ).copyWith (bottom: 12.0 ),
208+ child: AppText .header3 (label),
209+ ),
210+ ),
211+ sliver: SliverToBoxAdapter (
212+ child: Padding (
213+ padding: AppUiConstants .defaultScreenHorizontalPadding,
214+ child: child,
215+ ),
216+ ),
217+ );
218+ }
219+ }
220+
221+ class _PlaygroundColorBox extends StatelessWidget {
222+ const _PlaygroundColorBox ({
223+ required this .label,
224+ required this .color,
225+ required this .labelColor,
226+ });
227+
228+ final String label;
229+ final Color color;
230+ final Color labelColor;
231+
232+ final boxSize = 100.0 ;
233+
234+ @override
235+ Widget build (BuildContext context) {
236+ return Padding (
237+ padding: const EdgeInsets .all (6.0 ),
238+ child: Container (
239+ width: boxSize,
240+ height: boxSize,
241+ color: color,
242+ child: Center (
243+ child: Padding (
244+ padding: const EdgeInsets .all (8.0 ),
245+ child: AppText .body (
246+ label,
247+ textAlign: TextAlign .center,
248+ color: labelColor,
249+ ),
250+ ),
20251 ),
21252 ),
22253 );
@@ -32,12 +263,10 @@ class PlaygroundScreenOpenerButton extends StatelessWidget {
32263 return const SizedBox .shrink ();
33264 }
34265
35- return TextButton (
36- onPressed: () {
37- context.pushRoute (const PlaygroundRoute ());
38- },
39- child: const Text (
40- 'Open Playground Screen' ,
266+ return AppButton .text (
267+ label: 'Open Playground Screen' ,
268+ onPressed: () => context.pushRoute (
269+ const PlaygroundRoute (),
41270 ),
42271 );
43272 }
0 commit comments