Skip to content

Commit edf7a1b

Browse files
Add initial preview and review cards to FWE (#12821)
@ericwindmill These are rather rough, so please do either modify these now or as a follow-up to match your vision for each lesson. --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent b419b5a commit edf7a1b

17 files changed

+624
-5
lines changed

site/lib/_sass/base/_base.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ picture {
9292
font-feature-settings: 'liga';
9393
-webkit-font-feature-settings: 'liga';
9494
-webkit-font-smoothing: antialiased;
95+
user-select: none;
9596

9697
&.ms-filled {
9798
font-variation-settings: 'FILL' 1;

site/lib/_sass/components/_summary-card.scss

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
background-color: var(--site-raised-bgColor-translucent);
33
border-radius: var(--site-radius);
44
border: 1px solid var(--site-inset-borderColor);
5+
margin-block: 1rem;
56

67
header {
78
padding: 1rem 1.2rem 1.2rem;
@@ -10,13 +11,13 @@
1011

1112
>div {
1213
flex: 1;
13-
color: var(--site-base-fgColor-alt);
14+
color: var(--site-base-fgColor-lighter);
1415
}
1516

1617
h3 {
1718
margin: 0;
1819
font-size: 1.25rem;
19-
font-weight: 600;
20+
font-weight: 700;
2021
color: var(--site-base-fgColor);
2122
}
2223

@@ -47,6 +48,7 @@
4748

4849
font-size: 1rem;
4950
font-weight: 500;
51+
font-family: var(--site-ui-fontFamily);
5052
}
5153
}
5254

@@ -75,7 +77,7 @@
7577
margin: 0;
7678
border-top: 1px solid var(--site-inset-borderColor);
7779
padding: .8rem 1.2rem;
78-
color: var(--site-base-fgColor-alt);
80+
color: var(--site-base-fgColor-lighter);
7981

8082
>:last-child {
8183
margin-bottom: 0;

src/content/learn/tutorial/adaptive-layout.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ layout: tutorial
55
sitemap: false
66
---
77

8+
<SummaryCard>
9+
title: What you'll accomplish
10+
items:
11+
- title: Create responsive layouts with LayoutBuilder
12+
icon: fit_screen
13+
- title: Detect screen size to choose different layouts
14+
icon: devices
15+
- title: Build a sidebar and detail layout for large screens
16+
icon: view_sidebar
17+
</SummaryCard>
18+
819
Modern apps need to work well on screens of all sizes.
920
On this page, you'll learn how to create layouts that
1021
adapt to different screen widths.
@@ -353,3 +364,29 @@ Both the sidebar and main content area show placeholder text for now.
353364

354365
In the next lesson, you'll implement slivers to fill in
355366
the contact list content.
367+
368+
<SummaryCard>
369+
title: What you accomplished
370+
subtitle: Here's a summary of what you built and learned in this lesson.
371+
completed: true
372+
items:
373+
- title: Created responsive layouts with LayoutBuilder
374+
icon: fit_screen
375+
details: >-
376+
`LayoutBuilder` provides the parent's size constraints in
377+
its builder callback. By checking `constraints.maxWidth`,
378+
you can decide which layout to show based on available space.
379+
- title: Detected screen size to choose different layouts
380+
icon: devices
381+
details: >-
382+
You used a 600-pixel breakpoint to
383+
distinguish phone-sized screens from tablet-sized screens.
384+
This common threshold helps your app adapt its UI to
385+
provide the best experience on each device.
386+
- title: Built a sidebar and detail layout for large screens
387+
icon: view_sidebar
388+
details: >-
389+
On large screens, you displayed a fixed-width sidebar and
390+
an `Expanded` detail panel side-by-side using a `Row`.
391+
This classic pattern maximizes screen real estate on tablets and desktops.
392+
</SummaryCard>

src/content/learn/tutorial/advanced-ui.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ layout: tutorial
77
sitemap: false
88
---
99

10+
<SummaryCard>
11+
title: What you'll accomplish
12+
items:
13+
- title: Preview the Rolodex app you'll build
14+
icon: preview
15+
- title: Set up a project with Cupertino widgets
16+
icon: phone_iphone
17+
- title: Create data models for contacts and groups
18+
icon: data_object
19+
</SummaryCard>
20+
1021
In this third installment of the Flutter tutorial series,
1122
you'll use Flutter's Cupertino library to build a
1223
partial clone of the iOS Contacts app.
@@ -517,3 +528,29 @@ With all the extraneous code out of the way, in the next lesson,
517528
you'll start building the app in earnest.
518529

519530
[`cupertino_icons` package]: {{site.pub-pkg}}/cupertino_icons
531+
532+
<SummaryCard>
533+
title: What you accomplished
534+
subtitle: Here's a summary of what you built and learned in this lesson.
535+
completed: true
536+
items:
537+
- title: Previewed the Rolodex app
538+
icon: preview
539+
details: >-
540+
You're starting a new tutorial section focused on advanced UI features.
541+
To make your app feel polished and native on any device,
542+
you'll learn adaptive layouts, slivers, navigation, and theming.
543+
- title: Set up a project with Cupertino widgets
544+
icon: phone_iphone
545+
details: >-
546+
Unlike the previous lessons,
547+
this app uses `CupertinoApp` instead of `MaterialApp`.
548+
The Cupertino design system provides iOS-style widgets that
549+
feel native on Apple devices.
550+
- title: Created data models for contacts and groups
551+
icon: data_object
552+
details: >-
553+
You created `Contact` and `ContactGroup` classes with sample data,
554+
plus a `ContactGroupsModel` for state management.
555+
This foundation supports the UI you'll build in the coming lessons.
556+
</SummaryCard>

src/content/learn/tutorial/change-notifier.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ layout: tutorial
55
sitemap: false
66
---
77

8+
<SummaryCard>
9+
title: What you'll accomplish
10+
items:
11+
- title: Create a ViewModel with ChangeNotifier
12+
icon: layers
13+
- title: Manage loading, success, and error states
14+
icon: toggle_on
15+
- title: Signal UI updates with notifyListeners
16+
icon: notifications_active
17+
</SummaryCard>
18+
819
When developers talk about state-management in Flutter,
920
they're essentially referring to the pattern by which your app
1021
updates the data it needs to render correctly and then
@@ -192,3 +203,31 @@ class MainApp extends StatelessWidget {
192203
Hot reload your app and check your console output.
193204
You should see either an article title or an error message,
194205
which confirms that your Model and ViewModel are wired up correctly.
206+
207+
<SummaryCard>
208+
title: What you accomplished
209+
subtitle: Here's a summary of what you built and learned in this lesson.
210+
completed: true
211+
items:
212+
- title: Created the ArticleViewModel with ChangeNotifier
213+
icon: layers
214+
details: >-
215+
The ViewModel sits between your UI and Model,
216+
managing state and connecting the two layers.
217+
By extending `ChangeNotifier`, your ViewModel gains the ability to
218+
notify listeners when data changes.
219+
- title: Managed loading, success, and error states
220+
icon: toggle_on
221+
details: >-
222+
Your ViewModel tracks three pieces of state:
223+
`loading`, `summary`, and `errorMessage`.
224+
Using `try` and `catch`, you handle network errors gracefully and
225+
maintain consistent state for each possible outcome.
226+
- title: Used notifyListeners to signal UI updates
227+
icon: notifications_active
228+
details: >-
229+
Calling `notifyListeners()` tells any listening widgets to rebuild.
230+
You call it after setting `loading = true` and again
231+
after the operation completes.
232+
This is how you can implement reactive UI updates in Flutter.
233+
</SummaryCard>

src/content/learn/tutorial/create-an-app.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ sitemap: false
99
<!-- TODO(ewindmill) embed video -->
1010
{%- endcomment %}
1111

12+
<SummaryCard>
13+
title: What you'll accomplish
14+
items:
15+
- title: Create a new Flutter project using the CLI
16+
icon: terminal
17+
- title: Understand widgets and the widget tree
18+
icon: account_tree
19+
- title: Run your app and use hot reload
20+
icon: bolt
21+
</SummaryCard>
22+
1223
In this first section of the Flutter tutorial,
1324
you'll build the core UI of an app called 'Birdle',
1425
a game similar to [Wordle, the popular New York Times game][].
@@ -129,3 +140,32 @@ Change the text inside the string to anything you want.
129140
Then, hot-reload your app by
130141
pressing `r` in the terminal where the app is running.
131142
The running app should instantly show your updated text.
143+
144+
<SummaryCard>
145+
title: What you accomplished
146+
subtitle: Here's a summary of what you built and learned in this lesson.
147+
completed: true
148+
items:
149+
- title: Created your first Flutter project
150+
icon: terminal
151+
details: >-
152+
You used `flutter create` with the `--empty` flag to
153+
scaffold a minimal Flutter project.
154+
The CLI generates the project structure and
155+
boilerplate code needed to get started.
156+
- title: Explored the widget tree
157+
icon: account_tree
158+
details: >-
159+
Flutter UIs are built by composing **widgets** into a tree structure.
160+
The `runApp` function takes a root widget, and that widget's
161+
`build` method returns other widgets, forming the **widget tree**.
162+
Your job as a Flutter developer is to
163+
compose these widgets into custom UIs.
164+
- title: Ran your app with hot reload
165+
icon: bolt
166+
details: >-
167+
You ran your app with `flutter run` and
168+
experienced **stateful hot reload**, which lets you
169+
see code changes reflected in under a second without losing app state.
170+
Press `r` in the terminal to trigger a hot reload.
171+
</SummaryCard>

src/content/learn/tutorial/devtools.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ sitemap: false
77

88
{%- comment %} TODO(ewindmill) embed video {%- endcomment %}
99

10+
<SummaryCard>
11+
title: What you'll accomplish
12+
items:
13+
- title: Explore your app's widget tree with the widget inspector
14+
icon: account_tree
15+
- title: Learn to debug layout issues like unbounded constraints
16+
icon: bug_report
17+
- title: Experiment with properties in real-time
18+
icon: tune
19+
</SummaryCard>
20+
1021
As your Flutter app grows in complexity, it becomes more important
1122
to understand how each of the widget properties affects the UI.
1223
The [Dart and Flutter DevTools][] provide you with
@@ -188,3 +199,31 @@ change the numerical value in the property editor.
188199
Then instantly see the update on your running app without
189200
needing to recompile or even hot reload.
190201
This allows for rapid iteration on UI design.
202+
203+
<SummaryCard>
204+
title: What you accomplished
205+
subtitle: Here's a summary of what you built and learned in this lesson.
206+
completed: true
207+
items:
208+
- title: Explored your app's widget tree with the widget inspector
209+
icon: account_tree
210+
details: >-
211+
The widget inspector lets you visualize your entire widget tree,
212+
select any widget to view its properties, and
213+
jump directly to its source code.
214+
It's an essential tool for understanding your app's structure.
215+
- title: Learned about common layout issues
216+
icon: bug_report
217+
details: >-
218+
You learned about **unbounded constraints**,
219+
one of the most common errors hit in Flutter development.
220+
This happens when widgets like
221+
`Row`, `Column`, or `ListView` receive infinite constraints.
222+
Now you can recognize and fix these issues when they occur.
223+
- title: Experimented with properties in real-time
224+
icon: tune
225+
details: >-
226+
The property editor shows all properties of a selected widget and
227+
lets you modify values instantly with no recompiling or hot reload needed.
228+
This enables rapid iteration when fine-tuning your UI.
229+
</SummaryCard>

src/content/learn/tutorial/http-requests.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ layout: tutorial
55
sitemap: false
66
---
77

8+
<SummaryCard>
9+
title: What you'll accomplish
10+
items:
11+
- title: Understand the MVVM architecture pattern
12+
icon: layers
13+
- title: Build HTTP requests with async/await
14+
icon: cloud_download
15+
- title: Handle errors and parse JSON responses
16+
icon: data_object
17+
</SummaryCard>
18+
819
The overarching pattern that this tutorial implements is called
920
_Model-View-ViewModel_ or _MVVM_.
1021
MVVM is an [architectural pattern][] used in client apps that
@@ -135,3 +146,32 @@ check out the [Getting started with Dart][] tutorial.
135146
[Wikipedia API]: https://en.wikipedia.org/api/rest_v1/
136147
[JSON]: {{site.dart-site}}/tutorial/json
137148
[Getting started with Dart]: {{site.dart-site}}/tutorial
149+
150+
<SummaryCard>
151+
title: What you accomplished
152+
subtitle: Here's a summary of what you built and learned in this lesson.
153+
completed: true
154+
items:
155+
- title: Understood the MVVM architecture pattern
156+
icon: layers
157+
details: >-
158+
MVVM separates your app into Model (data operations),
159+
View (user interface), and ViewModel (state management).
160+
This separation of concerns makes your code more
161+
testable, reusable, and easier to maintain.
162+
- title: Built an HTTP request to fetch Wikipedia data
163+
icon: cloud_download
164+
details: >-
165+
You created an `ArticleModel` class with a method that
166+
uses `async` and `await` to fetch data from the Wikipedia API.
167+
To safely build the URLs for the requests,
168+
you used the `Uri.https` constructor which
169+
handles encoding and special characters for you.
170+
- title: Handled errors and parsed JSON responses
171+
icon: data_object
172+
details: >-
173+
You checked the HTTP status code to detect errors and
174+
used `jsonDecode` to parse the response body.
175+
Then to convert the raw JSON into a typed Dart object,
176+
you used the `Summary.fromJson` named constructor.
177+
</SummaryCard>

0 commit comments

Comments
 (0)