-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Design pattern index page #11468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Design pattern index page #11468
Changes from 13 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
27d300c
checkin initial expansion list implementation
ericwindmill d7833c5
Merge branch 'main' of https://github.com/flutter/website into design…
ericwindmill b9cc497
compleye expansion list scss
ericwindmill c01a730
finish draft
ericwindmill 27f49ea
fix jank
ericwindmill 6bb2626
remove commented code
ericwindmill 62e1f38
finish data yml file and tags html
ericwindmill 9c05942
add three more icons
ericwindmill f213dd3
add result and command
ericwindmill 2ed01e3
checkin updated figma file
ericwindmill beae98a
fix sql icon
ericwindmill bbca37a
fix link
ericwindmill 5e13792
Merge branch 'main' into design-pattern-index
ericwindmill d8f7cc4
Merge branch 'main' of https://github.com/flutter/website into design…
ericwindmill 2ffea51
replace data file with collections feature
ericwindmill e061967
Merge branch 'design-pattern-index' of https://github.com/flutter/web…
ericwindmill 8e86881
clean up
ericwindmill cdb6ff8
more cleanup
ericwindmill c970b2b
more cleanup
ericwindmill 62fb9d3
Merge branch 'main' into design-pattern-index
ericwindmill 0b50b92
sort recipes
ericwindmill 8a29475
Update design-patterns.md
ericwindmill 40fe7cc
Add action to page description
parlough 85165a5
Minor style cleanup and fixes
parlough 3c286c7
Slightly increase collapse duration
parlough 40ce1d4
Adjust naming of data
parlough bfdd563
move design patterns
ericwindmill 9837485
fix links
ericwindmill 18bc3fd
move code excerpts out of cookbook
ericwindmill 6e724a5
fix link typo
ericwindmill 7313cb4
fix utils path in code excerpts
ericwindmill File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| - title: "Persistent storage architecture: Key-value data" | ||
| tags: | ||
| - data | ||
| - shared-preferences | ||
| - dark mode | ||
ericwindmill marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| description: Save application data to a user's on-device key-value store. | ||
| path: /cookbook/architecture/key-value-data | ||
| img: /assets/images/docs/app-architecture/design-patterns/kv-store-icon.svg | ||
| body: | | ||
| 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, user preferences or data that should be available offline. | ||
|
|
||
| In this recipe, you will learn how to integrate persistent storage for key-value | ||
| data in a Flutter application by implementing a switchable light-mode and dark-mode theme | ||
| in an application and storing the users preference. | ||
parlough marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - title: "Persistent storage architecture: SQL" | ||
| tags: | ||
| - data | ||
| - SQL | ||
| description: Save complex application data to a user's device with SQL. | ||
| path: /cookbook/architecture/sql | ||
| img: /assets/images/docs/app-architecture/design-patterns/sql-icon.svg | ||
| body: | | ||
| Most Flutter applications, no matter how small or big they are, | ||
| might require storing data on the user’s device at some point. | ||
| For example, API keys, user preferences or data that should be available offline. | ||
|
|
||
| In this recipe, you will learn how to integrate persistent storage | ||
| for complex data using SQL by implementing a todo-list app that | ||
| follows our recommended Flutter app architecture. | ||
| - title: Offline-first support | ||
| description: Implement offline-first support for one feature in an application. | ||
| tags: | ||
| - data | ||
| - user experience | ||
| - repository pattern | ||
| path: /cookbook/architecture/offline-first | ||
| img: /assets/images/docs/app-architecture/design-patterns/offline-first-icon.svg | ||
| body: | | ||
| An offline-first application is an app capable of offering most or all of its | ||
| functionality while being disconnected from the internet. | ||
| Offline-first applications usually rely on stored data to offer users temporary access | ||
| to data that would otherwise only be available online. | ||
|
|
||
| Some offline-first applications combine local and remote data seamlessly, while other applications | ||
| inform the user when the application is using cached data. In the same way, | ||
| some applications synchronize data in the background while others require the | ||
| user to explicitly synchronize it. It all depends on the application requirements and | ||
| the functionality it offers, and it’s up to the developer to decide which implementation fits their needs. | ||
|
|
||
| In this guide, you will learn how to implement different approaches to offline-first | ||
| in Flutter applications that follow our recommended architecture guidelines. | ||
| - title: Optimistic state | ||
| description: Improve the perception of responsiveness of an application by implementing optimistic state. | ||
| tags: | ||
| - user experience | ||
| - asynchronous dart | ||
| path: /cookbook/architecture/optimistic-state | ||
| img: /assets/images/docs/app-architecture/design-patterns/optimistic-state-icon.svg | ||
| body: | | ||
| When building user experiences, the perception of performance is sometimes just as | ||
| important as the actual performance of the code. In general, users don’t like | ||
| waiting for an action to finish to see the result, and anything that takes more | ||
| than a few milliseconds could be considered “slow” or “unresponsive” from the user’s perspective. | ||
|
|
||
| Developers can help mitigate this negative perception by presenting a successful UI | ||
| state before the background task is fully completed. An example of this would be | ||
| tapping a “Subscribe” button, and seeing it change to “Subscribed” instantly, even if the | ||
| background call to the subscription API is still running. | ||
|
|
||
| This technique is known as Optimistic State, Optimistic UI or Optimistic User Experience. | ||
| In this recipe, you will implement optimistic state for a feature in an application that follows our | ||
| recommended architecture guidelines. | ||
| - title: The command pattern | ||
| description: Simplify view model logic by implementing a Command class. | ||
| tags: | ||
| - mvvm | ||
| - asynchronous dart | ||
| - state | ||
| path: /cookbook/architecture/command | ||
| img: /assets/images/docs/app-architecture/design-patterns/command-icon.svg | ||
| body: | | ||
| A command is a class that wraps a method and helps to handle the different | ||
| states of that method, such as running, complete, and error. | ||
|
|
||
| View models can use commands to handle interaction and run actions. | ||
| They can also be used to display different UI states, | ||
| like loading indicators when an action is running, | ||
| or an error dialog when an action failed. | ||
|
|
||
| View models can become very complex as an application grows | ||
| and features become bigger. | ||
| Commands can help to simplify view models and reuse code. | ||
|
|
||
| In this guide, you will learn how to use the command pattern | ||
| to improve your view models. | ||
| - title: Better error handling | ||
| description: Improve error handling across classes with Result objects. | ||
| tags: | ||
| - error handling | ||
| - services | ||
| path: /cookbook/architecture/result | ||
| img: /assets/images/docs/app-architecture/design-patterns/result-icon.svg | ||
| body: | | ||
| Dart provides a built-in error handling mechanism | ||
| with the ability to throw and catch exceptions. | ||
|
|
||
| Dart’s exceptions are unhandled exceptions. | ||
| This means that methods that throw exceptions don’t need to declare them, | ||
| and calling methods aren't required to catch them either. | ||
|
|
||
| This can lead to situations where exceptions are not handled properly. | ||
| In large projects, developers might forget to catch exceptions, | ||
| and the different application layers and components | ||
| could throw exceptions that aren’t documented. | ||
| This can lead to errors and crashes. | ||
|
|
||
| In this guide, you will learn about this limitation | ||
| and how to mitigate it using the result pattern. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| {%- comment -%} | ||
| This component expects a list of article or page objects. | ||
| Each article should have the following attributes: | ||
| - title: String - name of the article | ||
| - description: String - 1-2 sentence description of the article | ||
| - tags: List<String> - A short list of items that describe what the reader can expect from the content or format. | ||
| i.e. data, user-experience OR tutorial, 10 minute read | ||
| - body: String - This is the text body of the expandable portion of expansion panel. | ||
| - img: String - the path to an image that is shown in next to the title | ||
| - path: String - Path to the article or page | ||
| {%- endcomment -%} | ||
|
|
||
| <div class="expansion-panel-list"> | ||
| {% for item in list -%} | ||
| {% assign id = base_id | 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"> | ||
| <img src="{{item.img}}" alt="Alt text" /> | ||
| </div> | ||
| <div class="expansion-panel-title-content"> | ||
| <p class="content-title">{{item.title}}</p> | ||
| <ul class="content-tags"> | ||
| {% for tag in item.tags -%} | ||
| <li class="tag">{{tag}}</li> | ||
| {% endfor -%} | ||
| </ul> | ||
| <p class="content-description">{{item.description}}</p> | ||
| </div> | ||
| </div> | ||
| </a> | ||
| <div class="expansion-panel-body collapse {{show}}" id="{{id}}"> | ||
| <p>{{item.body}}</p> | ||
| <a href="{{item.path}}">Read full article</a> | ||
| <!-- Required to add "margin" that doesn't cause expansion jank --> | ||
| <div class="separator"></div> | ||
| </div> | ||
| </div> | ||
| {% endfor -%} | ||
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| @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; | ||
|
|
||
| // Add padding on small screens, because images aren't displayed. | ||
| @include bootstrap.media-breakpoint-down(md) { | ||
| padding-left: 1rem; | ||
| } | ||
|
|
||
| // Rotates chevron | ||
| @mixin collapsible() { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding-right: 1rem; | ||
|
|
||
| &::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: 0.15s; | ||
| } | ||
|
|
||
| &:not(.collapsed) { | ||
| &::after { | ||
| content: 'keyboard_arrow_down' / ''; | ||
| 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 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: ''; | ||
| 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: 2rem; | ||
| } | ||
|
|
||
|
|
||
| .separator { | ||
| margin-bottom: 3rem; | ||
| } | ||
| } | ||
|
|
||
| :last-child { | ||
| .expansion-panel-body { | ||
| border-bottom: none; | ||
| } | ||
| } | ||
| } | ||
ericwindmill marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| --- | ||
| title: Architecture design patterns | ||
| short-title: Design patterns | ||
| description: > | ||
| TODO | ||
| 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 = cookbook.design_patterns | sort: 'name' -%} | ||
| {% render expansion-list.html, list: recipes, base_id: 'design-patterns' %} | ||
|
|
||
| [architecture guide]: /app-architecture/guide |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.