We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Creating fluid app-like experiences with Ember

00:00

Formal Metadata

Title
Creating fluid app-like experiences with Ember
Title of Series
Number of Parts
27
Author
License
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language
Producer
Production Year2018

Content Metadata

Subject Area
Genre
Abstract
Mobile apps have UI patterns and features not often found in (mobile) web applications. We will take an in-depth look at ways to enhance user interaction for responsive Ember applications without having to develop a completely separate application. Topics include application organization, templating concerns, interaction patterns, relevant addons and a display of newly built Ember addons to fill in for missing interaction features.
VideoconferencingMobile appLinker (computing)Installation artCloud computingWeb pageContext awarenessEuclidean vectorView (database)AreaMenu (computing)Greatest elementElectronic data interchangeComputer iconCorrelation and dependencePrice indexGroup actionComponent-based software engineeringPattern languageComputer scienceProjective planeWebsiteStandard deviationMetropolitan area networkFlow separationBitMusical ensembleGroup actionContext awarenessVelocityConnectivity (graph theory)Greatest elementElement (mathematics)RobotPosition operatorLimit (category theory)TouchscreenContent (media)Multiplication signWeb 2.0Data miningTwitterWeb-DesignerMenu (computing)Auditory maskingLibrary (computing)INTEGRAL1 (number)Formal grammarMobile appState observerWeb browserWrapper (data mining)HyperplaneRevision controlSpacetimePhysical systemOrder (biology)MereologyClosed setDigital rights managementWindowWeb pageBookmark (World Wide Web)Source codeDoubling the cubeRow (database)State of matterPersonal area networkSoftware as a serviceBuildingLink (knot theory)Web applicationView (database)VideoconferencingXMLComputer animationLecture/Conference
Event horizonMenu (computing)Element (mathematics)Pattern recognitionEntire functionWeb browserGraphical user interfaceMobile WebEuclidean vectorQuery languagePersonal area networkInfinityComponent-based software engineeringPressure volume diagramConcurrency (computer science)Motion capturePhase transitionDefault (computer science)Set (mathematics)Motion captureEvent horizonConnectivity (graph theory)Standard deviationInference engineDaylight saving timeElement (mathematics)Price indexInteractive televisionMenu (computing)Electronic visual displayMusical ensembleWeb browserSimilarity (geometry)Category of beingFinite-state machineLevel (video gaming)NavigationVelocityPhase transitionGraphical user interfaceService (economics)Integrated development environmentMobile appEndliche ModelltheorieExecution unitAngleDistancePattern recognitionGroup actionWrapper (data mining)Incidence algebraBitCASE <Informatik>Template (C++)Task (computing)WindowFamilyServer (computing)Type theoryRight angleParameter (computer programming)Limit (category theory)State of matterKnotRevision controlMultiplication signInsertion lossAsynchronous Transfer ModeLink (knot theory)Content (media)Roundness (object)PlanningoutputRoutingPersonal area networkConcurrency (computer science)Mobile WebPhysical systemCore dumpExpected valueInheritance (object-oriented programming)Dot product2 (number)Touch typingWebsiteDifferent (Kate Ryan album)Query languageSet (mathematics)Arithmetic progressionLatent heatComputer animationLecture/Conference
Inheritance (object-oriented programming)View (database)Web pageSlide ruleMorphismusFunction (mathematics)HierarchyEuclidean vectorPrice indexMobile WebSimilarity (geometry)Web portalImage resolutionRule of inferenceElement (mathematics)Singuläres IntegralInfinityMorphingMusical ensemblePrice indexDataflowView (database)Menu (computing)Group actionSingle-precision floating-point formatDependent and independent variablesEnterprise architectureWeb 2.0MeasurementWeb pageControl flowGreatest elementSimilarity (geometry)Slide ruleMobile WebDefault (computer science)CASE <Informatik>MereologyFunctional (mathematics)Cartesian coordinate systemIncidence algebraRight angleDigital rights managementConnectivity (graph theory)State of matterInformation securityTransformation (genetics)Semiconductor memoryMobile appSet (mathematics)Level (video gaming)Matching (graph theory)Point (geometry)Sound effectTemplate (C++)TouchscreenElement (mathematics)WebsiteContext awarenessRule of inferenceReduction of orderDirection (geometry)HierarchyRoutingNormal (geometry)outputRouter (computing)OntologyBootingBootstrap aggregatingContent (media)InfinityRow (database)2 (number)Ocean currentComputer animationLecture/Conference
Cross-site scriptingHypermediaQuery languageMenu (computing)Price indexWeb pageVolumenvisualisierungEuclidean vectorComa BerenicesPosition operatorVisualization (computer graphics)Cycle (graph theory)Group actionSet (mathematics)Right angleArtistic renderingKritischer Punkt <Mathematik>Computer animation2 (number)Menu (computing)Utility softwareHypermediaFamilyQuery languageMultiplication signExistential quantificationIntegrated development environmentSpacetimeWeb 2.0PlanningSubject indexingOrientation (vector space)Connectivity (graph theory)Concurrency (computer science)Pattern languageTouchscreenMobile WebWeb pagePoint (geometry)Social classLink (knot theory)Different (Kate Ryan album)Demo (music)Category of beingElectronic mailing listControl flowDefault (computer science)Template (C++)Mobile appArithmetic progressionSlide ruleDecimalTerm (mathematics)Endliche ModelltheorieNeuroinformatikBlock (periodic table)Bootstrap aggregatingRouter (computing)Dependent and independent variablesDifferenz <Mathematik>Installation artState of matterRoutingView (database)Personal area networkHookingBootingComputer animationLecture/Conference
Demo (music)Traffic reportingOntologyDependent and independent variablesAlpha (investment)Revision controlMobile appComputer animationLecture/Conference
Linker (computing)Square numberCloningDaylight saving timeRow (database)Coma BerenicesComputer animationXML
Block (periodic table)Data typeComputer animation
Transcript: English(auto-generated)
My name is Nick, I flew all the way from the Netherlands to bring you this talk.
I run a small web development company called web app with a friend of mine and I'm currently finishing my computer science master at the University of Twente. You can find me on GitHub, on Twitter, on my own website. So, I too started a side project six months ago and I wanted to create an ember app in
the browser which felt as much as a native app as possible. I took an experimental approach to this as I didn't really know what was possible yet. So what I did was create an app, build things and when they grew enough I put them into
separate add-ons and I'm going to show you today what made the cut. So first things first, I initialized a new ember app of course. I installed some of my favorite tools, SaaS and Ember Bootstrap just to get things going
quickly and then I thought hey, what do we actually need to create an app-like experience? So there's a few basic UI elements that most apps have like toolbars, either bottom or top bars, side menus especially on Android, they're really common, panes through which
you can pan and then also the pan gesture support, app-like transitions, that's a really important part in the actual app experience and scroll state management.
So then I started looking into the ember ecosystem of course, I opened up ember observer and took a look at what's actually available. One of the most important things I installed first was ember gestures which is a gesture
wrapper around the hammer.js gesture library. It provides easy integration for gestures in ember components. Then of course we all heard about it yesterday, ember animated for cool transitions. And then I took a look at a few of the sidebar add-ons available, ember burger menu
is one of the most well-known ones but it didn't really provide what I was looking for, it has some basic gesture support where you can swipe to open but not actually drag, ember side menu is actually one that does that but I discovered it too late
and it didn't support or I had already solved a few problems in my own add-on which would still be there with this add-on. So, the first component I created was a toolbar component.
Apps usually have either a fixed bar at the top, at the bottom or both. The rest of the screen is then filled with a scrollable viewport where the content of the app is visible. The bars can be in the context of the page so that when you animate into a new context
the bars animate with the page. Now in the browser this is a little harder, during my experimentation I found that using the body as the scrolling element was the most reliable way to actually implement these bars and this means the bars must be positioned fixed which later brought along a new problem
which is actually a limitation of the CSS standard covering this and that standard is that a position fixed element within an element which has a CSS transform is actually
not positioned relatively to the window anymore which completely destroys the purpose of position fixed because it's now not stuck to the top of your window anymore. So this means we must actually define these bars high up in the DOM so we can prevent
this as we'd like to add cool animations which actually use transform to the pages. So the actual component, I created a wrapper component which manages the bars. You can yield either a top or bottom bar from this wrapper component and what you get
is then this, you can see that it's a little different from the app version as the scroll bar is actually covering the entire viewport. The wrapper will adjust its spacing to accommodate for the space the bars take up
so that your content will always be visible. And then there's another cool feature which mobile bars can have in apps which I also ported over and that's actually the bar auto hides on downward scroll and comes back
into view immediately when you scroll up again as you can see in the video. You can optionally set the collapsible height of the top bar so that you can create a double row menu like thing where only the top part collapses so the menu stays in view
all the time. This also works for the bottom bar. It works in an inverse way so when you scroll down that will collapse to the bottom. Then onto the sidebar menu. So this is actually a very common way to do menus in websites.
You get a hamburger button in the most annoying position possible and the menu items are also still in a pretty hard to reach place. On Android this is actually solved pretty nicely. They pull down the menu items a little bit so you can reach them easier.
The menu is a full height scrollable menu on the left side or the right side and there's a mask which closes the menu. Then this menu also has gesture support so you can pan from the edge to open it and you can pan on the menu to close it so if you start
your pan on the mask it will not actually trigger the panning action until you reach the side menu. You can of course also swipe it with a high enough velocity to either close or open it. This again is a wrapper component from which you can yield the menu.
You can ask it for a side. Both left and right are supported as I said before and then also an extended link to component is provided which closes the menu when you transition into a new route. Then how does the edge pan recognition work? Because our wrapper
is actually defined high up in the DOM so the entire element will get pan recognition events. Basically what I did was check if there's any menu defined, whether it's false, then I checked the edges, checked whether or not the pan start event is within the
edges and then set it active. Now those of you with an iPhone might think hey I already have an edge gesture in my browser and that's true. This conflicts with the browser's
pan to go back causing some very funky behavior and unfortunately we can't use edge gestures in the iOS browser so we have to detect them when we are in a browser environment on iOS. The pan to go back gesture is actually disabled when you add the app to
the home screen. So we can use Amber user agent which is a nice add-on to actually detect the iOS environment and then use the window.navigator.standalone property which is Safari specific to detect whether or not we are running from home. Now when we add
this to our pan start event it won't trigger on iOS in the browser environment. For Chrome and Firefox there's a similar work in progress standard called display mode standalone which you can also use to detect a standalone browser. Then finally what you get is this
menu as you can see the pan event nicely closes the menu. Next up is the pane. This is actually the most complex component I created. There's two basic features I wanted
to support. So first up there's the tab like component through which you can pan. You can put arbitrary content in the templates. This does mean you cannot pan between routes
so the best we can do here is use query parameters to actually keep the state of the tabs. And then the other thing I wanted to do was pan between resource routes so you have routes like in this case a post route where the template is the same but only the model differs. We can actually pan between those. Then the components for
the there's again a wrapper component which manages the entire component. You can yield a navigation from it which I will show later and then put in the panes in
the scroller. You can add a title which will show up in the navigation and add your content there. The infinite panes work a little bit differently. You provide a previous model, a current model and a next model of which either the previous or the next model can be null. And then that's it. You can now pan between routes. And then
I had an idea. There's actually another way we can use this. A carousel is basically a set of panes with limited interaction and time change. So we just need to add a
simpler indicator with the nice dots which follows the pan movement. And then use the famous Amber concurrency to add a task, yielding a timeout of five seconds and then changing to the new pane. We start this task when we insert the component and then when the
user interacts with it, we interrupt the task. And when either the mouse leaves or the touch ends, we restart the task again and now we have a carousel. Then I was like, yay, everything works, I'm going to play with this. But, yeah, this is a new problem
showed up which you can see here. That's not good. And I was like, oh, no, what am I going to do? Yeah, we've all seen Maurice talk about events. Luckily for me, this is actually when the browser worked with me. There's actually another phase in
the whole event system which is the capture phase. That traverses down the DOM to the element on which the event happened and then you get the bubble phase which you probably all know which then handles the event. We can actually use this capture phase
but Ember works after bubble phase so we can't use Ember events and Ember gestures unfortunately doesn't support the capture phase so this is when I thought, oh, no, now, what do I do now? And this is actually when I started to write my own pen recognizer so I could
use it. What you need is basically touch events which are supported by modern browsers
and on each touch event you need the coordinates, the angle, the distance and the velocity of the movement. So we want to enable the capture phase optionally because usually you'd still like to use the bubble phase for example when you have nested panes or
whatever and we want to provide a locking service. Now back to the site menu, we will implement this new pan recognizer and this happens through a mix-in. We enable the capture
events for the site menu and then we will claim the lock on the valid edge pan so this way no pan events will happen on any other add-on using Ember mobile core
and now everything works as expected. This also enables nested panes so what you see here is actually a higher level multi-pane with the menu up top and a nested carousel
which will seamlessly flow over into the parent pane when you reach the edge. Also note the navigation at the top, it keeps the active item in the view so the user always
knows where he is and the indicator morphs between menu items. Then the next important part transitions with Ember animated. Why do we want transitions? Well when used correctly transitions will enhance the perceived responsiveness of a mobile app and will also unconsciously
or consciously inform the user of the context he is in. This is an example transition I have created which is inspired by iOS and what you see here is that the title of the previous page morphs into the back button and the new title flies in. The new
page will also slide over the old page and the old page slides away slightly. Now this is where I thought hey mobile transitions follow route hierarchy and context in a predictable
way so we can abstract this into a component. So just to remind you all this is what a normal Ember route hierarchy looks like. We have posts and then a detail page for single post and an edit route and what you'll notice is that with each of these you go one level deeper and we can actually completely abstract the transitions away. So
I've created a mobile page component and this component is aware of route transition direction using an application route mix-in. It will select the matching transition effect
and it will manage page and viewport style during transition which is harder than you might think. It also manages the scroll state. Currently it supports horizontal transitions between similar level panes of pages and the transitioning down and transitioning up
the route hierarchy and in the near future we will also support switching to an out of flow context or to a new context. This is basically the animation you get when you create a new post for example and then the page flies up from the bottom.
The top toolbar functions in a similar way to the mobile page. This is also a component I created. This component is meant to be used in a top toolbar. It provides several Ember Elsewhere portals to which you can send left buttons, titles, right buttons and a
second row of content. In the middle case the navigation and this component transitions on the same, based on the same rules as the mobile page component. Now managing scroll state. For the scroll state we can actually use the route hierarchy
again as it's quite clear how scroll state works in mobile apps. It should basically get restored when you're going up in the route hierarchy or sideways and get reset when you go back down. But we use document based scrolling and with all these transitioning
elements it's actually quite hard to manage the scroll state as the transitioning elements are not actually the scrolling elements. So during transition the scroll, the body size must actually be limited to prevent any weird scroll bars appearing during the
transition and we apply the scroll state as a CSS transform during this transition. Normally we'd use memory scroll or Ember router scroll which are two well known add
ons to manage scroll state but in this case we can't. So mobile page will manage that by itself as you can see the scroll state gets properly applied and restored as we go back and forth. The infinite scroller component has a similar approach but it uses
its own scroll state management. Then responsiveness. So we have a few tools we can use to create
or to make our app responsive in the web sense. There's Ember responsive in which you can define a set of break points, in this case I've defined the default bootstrap for break points and you can then in your template add an if check to see, to render
something only on mobile for example. But this may cause flicker when using fast boot as fast boot is not actually aware of the screen size you have. Luckily there's another approach and that's the CSS media queries you probably all know. And bootstrap has
some useful utilities to find out, to apply styles to the different break points and there's also some utility classes we can use. Now there's an example over here,
the settings menu, this is the index route of the settings menu containing the items and this is then a nested route with settings pages but this is probably not what you'd like on desktop, there's a lot more space, you don't want to show just the menu with
a few items. So how are we going to solve this? We can move the settings menu into a component and render it on the settings index route as well as the settings route on desktop and then you get the page as shown on the slide. But we cannot actually
use the settings index route anymore on desktop, so we'll have to redirect users when they're on desktop, we can again use the Amber responsive utility to do that. And then transitions, we put in those transitions, this doesn't really look nice on desktop, turns out mobile
transitions don't work well on desktop, so we'll have to turn them off. We can use Amber responsive to disable or modify these transitions. So I created a computer property checking whether or not transitions should be enabled and then in the template
just disable the complete animation if we're not on mobile. Then final remarks, we've seen a lot of great progressive web oriented things on this
conference and those are of course very important when creating a mobile app. You can add splash screens, icons, offline availability, native notifications and the add to home notification. Then there's also hybrid apps for which this will also work really well. This basically
means you put the Amber app into an installable web view. Then the final things you need to keep in mind, you must keep or will likely run into some problems when you're following default Amber, the default Amber router style. As you might know, model hooks block,
completely block rendering and as such also the visual transition and on mobile it's not really nice when you click an item, have to wait a couple of seconds, then a transition
happens. It kind of breaks the experience but there are some great resources on how to apply Amber concurrency based patterns to make the model hook async or use a loader component to asynchronously load the data. I've put links to these resources in the
demo app repository. Then I kept this one in too, it's quite important and it might also nicely finish your Amber Conf bingo. It's the swelled list rendering, rendering
takes a lot of time and especially during transitions performance may suffer when there's a lot of items on screen. There's actually a great add on called vertical collection to improve on this situation. Then is there still time left? Yeah, there's some time left.
So this is the finished app then. As you can see we have the side menu here, we can throw it around. There's the carousel and when we move here we have our nested pages
with the animations. These will keep scroll state. I'm actually completely on the other side. Here you can see the nested panning in action and you can actually just scroll
this navigation bar. I made no modifications there, that's just a diff which is scrollable. Here are the nested panes and the settings menu I showed before. Yeah and it's all completely
responsive. So you can try this yourself, I put the demo app online. Be sure to do so, report any glitches and the four add ons I've shown are available as alpha quality
versions on GitHub. Yeah and that was it. Thank you very much.