Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
27d300c
checkin initial expansion list implementation
ericwindmill Dec 5, 2024
d7833c5
Merge branch 'main' of https://github.com/flutter/website into design…
ericwindmill Dec 5, 2024
b9cc497
compleye expansion list scss
ericwindmill Dec 5, 2024
c01a730
finish draft
ericwindmill Dec 5, 2024
27f49ea
fix jank
ericwindmill Dec 6, 2024
6bb2626
remove commented code
ericwindmill Dec 6, 2024
62e1f38
finish data yml file and tags html
ericwindmill Dec 6, 2024
9c05942
add three more icons
ericwindmill Dec 6, 2024
f213dd3
add result and command
ericwindmill Dec 6, 2024
2ed01e3
checkin updated figma file
ericwindmill Dec 6, 2024
beae98a
fix sql icon
ericwindmill Dec 6, 2024
bbca37a
fix link
ericwindmill Dec 6, 2024
5e13792
Merge branch 'main' into design-pattern-index
ericwindmill Dec 8, 2024
d8f7cc4
Merge branch 'main' of https://github.com/flutter/website into design…
ericwindmill Dec 9, 2024
2ffea51
replace data file with collections feature
ericwindmill Dec 9, 2024
e061967
Merge branch 'design-pattern-index' of https://github.com/flutter/web…
ericwindmill Dec 9, 2024
8e86881
clean up
ericwindmill Dec 9, 2024
cdb6ff8
more cleanup
ericwindmill Dec 9, 2024
c970b2b
more cleanup
ericwindmill Dec 9, 2024
62fb9d3
Merge branch 'main' into design-pattern-index
ericwindmill Dec 10, 2024
0b50b92
sort recipes
ericwindmill Dec 10, 2024
8a29475
Update design-patterns.md
ericwindmill Dec 10, 2024
40fe7cc
Add action to page description
parlough Dec 11, 2024
85165a5
Minor style cleanup and fixes
parlough Dec 11, 2024
3c286c7
Slightly increase collapse duration
parlough Dec 11, 2024
40ce1d4
Adjust naming of data
parlough Dec 11, 2024
bfdd563
move design patterns
ericwindmill Dec 11, 2024
9837485
fix links
ericwindmill Dec 11, 2024
18bc3fd
move code excerpts out of cookbook
ericwindmill Dec 11, 2024
6e724a5
fix link typo
ericwindmill Dec 11, 2024
7313cb4
fix utils path in code excerpts
ericwindmill Dec 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified diagrams/app-architecture/architecture-docs.fig
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ dependencies:

dev_dependencies:
example_utils:
path: ../../../example_utils
path: ../../example_utils

flutter:
uses-material-design: true
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dev_dependencies:
build_runner: ^2.4.13
freezed: ^2.5.7
example_utils:
path: ../../../example_utils
path: ../../example_utils

flutter:
uses-material-design: true
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ dependencies:

dev_dependencies:
example_utils:
path: ../../../example_utils
path: ../../example_utils

flutter:
uses-material-design: true
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ dependencies:

dev_dependencies:
example_utils:
path: ../../../example_utils
path: ../../example_utils

flutter:
uses-material-design: true
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dev_dependencies:
freezed: ^2.5.7
json_serializable: ^6.8.0
example_utils:
path: ../../../example_utils
path: ../../example_utils

flutter:
uses-material-design: true
15 changes: 1 addition & 14 deletions src/_data/sidenav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -443,20 +443,7 @@
- title: Recommendations
permalink: /app-architecture/recommendations
- title: Design patterns
permalink: /cookbook/architecture
children:
- title: Optimistic state
permalink: /cookbook/architecture/optimistic-state
- title: Command
permalink: /cookbook/architecture/command
- title: Result
permalink: /cookbook/architecture/result
- title: "Persistent storage architecture: Key-value data"
permalink: /cookbook/architecture/key-value-data
- title: "Persistent storage architecture: SQL"
permalink: /cookbook/architecture/sql
- title: Offline-first
permalink: /cookbook/architecture/offline-first
permalink: /app-architecture/design-patterns

- title: Platform integration
permalink: /platform-integration
Expand Down
58 changes: 58 additions & 0 deletions src/_includes/expansion-list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{%- comment -%}
This component expects a list of article or page objects.
The frontmatter of each article should have the following attributes:
- title: String - name of the article
- description: String - 1-2 sentence description of the article
- contentTags: List<String> - A short list of items that describe what the reader
can expect from the content or describe meta information about the article.
i.e. data, user-experience OR tutorial, 10 minute read
- iconPath: String - the path to an image that is shown in next to the title
{%- endcomment -%}

<div class="expansion-panel-list">
{% for item in list -%}
{% assign id = baseId | append: '-expansion-' | append: forloop.index -%}
{% if item.expanded -%}
{% assign expanded = 'true' -%}
{% assign show = 'show' -%}
{% else -%}
{% assign class = 'collapsed' -%}
{% assign expanded = 'false' -%}
{% assign show = '' -%}
{% endif -%}
<div class="expansion-panel">
<a class="{{class}} collapsible"
data-toggle="collapse"
href="#{{id}}"
role="button"
aria-expanded="{{expanded}}"
aria-controls="{{id}}">
<div class="expansion-panel-title">
<div class="expansion-panel-title-leading">
{%- if item.data.iconPath %}
<img src="{{item.data.iconPath}}" alt="An icon showing a generic application." />
{%- else %}
<img src="/assets/images/docs/app-architecture/design-patterns/kv-store-icon.svg" alt="A ivon showing a generic application." />
{%- endif %}

</div>
<div class="expansion-panel-title-content">
<p class="content-title">{{item.data.title}}</p>
<ul class="content-tags">
{% for contentTag in item.data.contentTags -%}
<li class="tag">{{contentTag}}</li>
{% endfor -%}
</ul>
<p class="content-description">{{item.data.description}}</p>
</div>
</div>
</a>
<div class="expansion-panel-body collapse {{show}}" id="{{id}}">
<p>{{item.content | truncatewords: 100}} <a href="{{item.url}}">Read full article</a></p>

<!-- Required to add "margin" that doesn't cause expansion jank -->
<div class="separator"></div>
</div>
</div>
{% endfor -%}
</div>
2 changes: 2 additions & 0 deletions src/_sass/base/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ $site-color-sub-grey: #8d9399;
$site-color-nav-links: #6E7274;
$site-color-body: #212121; // Poor contrast with links
$site-color-body-light: color.scale($site-color-body, $lightness: 20%);
$site-color-body-caption: color.scale($site-color-body, $lightness: 30%);
$site-color-footer: #303c42;
$site-color-primary: $flutter-color-blue-500;
$twitter-color: #60CAF6;
$site-color-panel-background: color.scale($site-color-primary, $lightness: 95%);

// Fonts
$font-size-base-weight: 400;
Expand Down
149 changes: 149 additions & 0 deletions src/_sass/components/_expansion-list.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
@use '../base/variables' as *;
@use '../vendor/bootstrap';

.expansion-panel-list {
background: $site-color-panel-background;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 12px;
margin-top: 2rem;
margin-bottom: 2rem;

// Rotates chevron
@mixin collapsible() {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 1rem;

// Border radius to match entire list, so focus outline matches.
border-radius: 12px;

// Add padding on small screens, because images aren't displayed.
@include bootstrap.media-breakpoint-down(sm) {
padding-left: 1rem;

&:first-child {
// Add extra space above first expansion panel.
padding-top: 0.5rem;
}
}

&::after {
// Duplicated since Firefox doesn't support content alt text.
content: 'keyboard_arrow_down';
content: 'keyboard_arrow_down' / '';
font: $site-font-icon;
transition: transform .25s ease-in-out;
}

.collapsing {
transition-duration: .2s;
}

&:not(.collapsed) {
&::after {
transform: rotate(180deg);
}
}
}

.expansion-panel {
> a {
// Adds display:flex, align:center, and justify:space-between.
@include collapsible();
}

a:hover {
text-decoration: none;
}
}

.expansion-panel-title {
display: flex;
flex-direction: row;
align-items: center;

.expansion-panel-title-leading {
height: 8rem;
width: 8rem;
margin: .5rem;
padding: 1rem;

// Hide leading image on small screens.
display: none;

@include bootstrap.media-breakpoint-up(md) {
display: flex;
flex: 1 0 auto;
}

img {
margin: auto;
}
}

.expansion-panel-title-content {
.content-title {
color: $site-color-black;
font-size: 1rem;
font-weight: 500;
margin-bottom: .25rem;

@include bootstrap.media-breakpoint-up(md) {
font-size: 1.25rem;
}
}

.content-description {
color: $site-color-body;
margin-bottom: $site-spacer / 2;
}

.content-tags {
display: flex;
flex-direction: row;
list-style: none;
padding-left: 0;
margin-bottom: .75rem;

.tag {
color: $site-color-body-caption;
font-size: .8rem;
line-height: 1;
margin-bottom: 0;

&::after {
// Duplicated since Firefox doesn't support content alt text.
content: ' |\00a0';
content: ' |\00a0' / '';
}

&:last-child::after {
content: '';
}
}
}
}
}

.expansion-panel-body {
margin: auto;
width: 90%;
border-top: .05rem solid rgba(0, 0, 0, 0.125);

p {
color: $site-color-body;
margin-top: 1.5rem;
}

.separator {
margin-bottom: 3rem;
}
}

:last-child {
.expansion-panel-body {
border-bottom: none;
}
}
}
1 change: 1 addition & 0 deletions src/_sass/site.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@use 'components/content';
@use 'components/cookie-notice';
@use 'components/d2h';
@use 'components/expansion-list';
@use 'components/footer';
@use 'components/header';
@use 'components/juicy-button';
Expand Down
2 changes: 1 addition & 1 deletion src/content/app-architecture/case-study/data-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ completing the cycle.
[`APIClient`]: https://github.com/flutter/samples/blob/main/compass_app/app/lib/data/services/api/api_client.dart
[`sealed`]: {{site.dart-site}}/language/class-modifiers#sealed
[`BookingRepository` classes on GitHub]: https://github.com/flutter/samples/tree/main/compass_app/app/lib/data/repositories/booking
[Result cookbook recipe]: /cookbook/architecture
[Result cookbook recipe]: /app-architecture/design-patterns/result

[//]: # (todo ewindmill@ - update Result link after #11444 lands)

Expand Down
26 changes: 26 additions & 0 deletions src/content/app-architecture/design-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Architecture design patterns
short-title: Design patterns
description: >-
A collection of articles about useful design patterns for
building Flutter applications.
prev:
title: Recommendations
path: /app-architecture/recommendations
toc: false
---

If you've already read through the [architecture guide][] page,
or if you're comfortable with Flutter and the MVVM pattern,
the following articles are for you.

These articles aren't about high-level app architecture,
rather they're about solving specific design problems that improve your
application's code base regardless of how you've architected your app.
That said, the articles do assume the MVVM pattern laid out on the
previous pages in the code examples.

{% assign recipes = collections.design-patterns | sort: "data.order" -%}
{% render expansion-list.html, list: recipes, baseId: 'design-patterns' %}

[architecture guide]: /app-architecture/guide
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
---
title: Command pattern
description: >-
Learn how to improve your view models with commands.
title: The command pattern
description: "Simplify view model logic by implementing a Command class."
contentTags:
- mvvm
- asynchronous dart
- state
iconPath: /assets/images/docs/app-architecture/design-patterns/command-icon.svg
order: 4
js:
- defer: true
url: /assets/js/inject_dartpad.js
---

<?code-excerpt path-base="cookbook/architecture/command"?>
<?code-excerpt path-base="app-architecture/command"?>

[Model-View-ViewModel (MVVM)][] is a design pattern
that separates a feature of an application into three parts:
Expand Down Expand Up @@ -626,7 +631,7 @@ final class Command1<T, A> extends Command<T> {
```

[Compass App example]: {{site.repo.samples}}/tree/main/compass_app
[`Result` class]: /cookbook/architecture/result
[`Result` class]: /app-architecture/design-patterns/result
[pub.dev]: {{site.pub}}
[`flutter_command`]: {{site.pub-pkg}}/flutter_command
[`ChangeNotifier`]: /get-started/fundamentals/state-management
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"tags": "design-patterns"
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
---
title: "Persistent storage architecture: Key-value data"
description: Create a service to store key-value data
description: Save application data to a user's on-device key-value store.
contentTags:
- data
- shared-preferences
- dark mode
iconPath: /assets/images/docs/app-architecture/design-patterns/kv-store-icon.svg
order: 1
js:
- defer: true
url: /assets/js/inject_dartpad.js
---

<?code-excerpt path-base="cookbook/architecture/todo_data_service"?>
<?code-excerpt path-base="app-architecture/todo_data_service"?>

Most Flutter applications, no matter how small or big they are,
require storing data on the user’s device at some point, such as API keys,
Expand Down Expand Up @@ -358,5 +364,5 @@ ListenableBuilder(

[Flutter architecture design]: /app-architecture
[Store key-value data on disk]: /cookbook/persistence/key-value
[Persistent Storage Architecture: SQL]: /cookbook/architecture/sql
[Persistent Storage Architecture: SQL]: /app-architecture/design-patterns/sql
[`/examples/cookbook/architecture/todo_data_service/`]: {{site.repo.this}}/tree/main/examples/cookbook/architecture/todo_data_service/
Loading
Loading