{"id":143,"date":"2014-09-25T01:00:00","date_gmt":"2014-09-25T01:00:00","guid":{"rendered":"http:\/\/localhost\/?p=143"},"modified":"2017-01-09T06:50:11","modified_gmt":"2017-01-09T06:50:11","slug":"refreshing-pull-to-refresh","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh","title":{"rendered":"Refreshing our Pull-to-Refresh"},"content":{"rendered":"<p>For a while now, we\u2019ve wanted to update Pull To Refresh in Ionic. It worked, but it wasn\u2019t exciting, and since it\u2019s a goal of ours at Ionic to make every component as enjoyable to use as it can be, we decided it was time for a change. Here&#8217;s some of the lessons in semiotics and UX that we learned&#8230;<\/p>\n<p><!--more--><\/p>\n<p>Wanting to make it fun and playful, we started by binding the rotation of the arrow icon to how far you pull down the view. It was fun. <a href=\"https:\/\/twitter.com\/benjsperry\">Ben<\/a> and I spent a good ten minutes each just playing with pulling the view down. We quickly realized a problem, though: While it was fun, it was not practical. <\/p>\n<p>Most users don\u2019t sit and play with the pull to refresh animation on their phones; they \u201cuse\u201d their phones. They \u201cuse\u201d pull to refresh to get the information they want, and they want it now. That means they swipe up quickly and expect the pull to refresh to trigger and update. They swipe so fast, the animation doesn\u2019t even happen.<\/p>\n<div style=\"float: right; margin-right: -160px\">\n<div class=\"phone-case\">\n<p data-height=\"568\" data-theme-id=\"3572\" data-slug-hash=\"nqIrC\" data-default-tab=\"result\" class=\"codepen\">See the Pen by <a href=\"http:\/\/codepen.io\/ionic\/pen\/nqIrC\">Ionic<\/a> (<a href=\"http:\/\/codepen.io\/ionic\">@ionic<\/a>) on <a href=\"http:\/\/codepen.io\">CodePen<\/a>.<\/p>\n<p>  <script async=\"\" src=\"\/\/codepen.io\/assets\/embed\/ei.js\"><\/script>\n <\/div>\n<\/div>\n<p>So we went back to a regular fixed-time animation, updated the default icons to be something more visually appealing, and moved on. <\/p>\n<p>The next thing we noticed was that most API calls are pretty fast, perhaps too fast. Our refresher would return to the home position as soon as it was told the information requested was received. This meant that as soon as you let go of the refresher when swiping up, it wouldn\u2019t spin; instead, it would return immediately to the home position. We have an internal Hacker News app we were using to test this (more info on that soon). The front page of Hacker News doesn\u2019t update every five seconds, so most of the time, a refresh does nothing. We were left unsure if an update actually fired. <\/p>\n<p>Setting up console logs allows developers to make sure the refresh actually happened. Users don\u2019t get the reassurance of a console log, though, so your UI must be reassuring enough on its own.<\/p>\n<p>We decided to force 400ms of the refreshing spinner animation. If the data came back sooner, we\u2019d still apply it immediately, but we\u2019d show the spinner for a bit, so the user would know a refresh had happened. To a developer, this may feel misleading. The refresh is already complete, so why are we still showing the animation?<\/p>\n<p><strong>Users don\u2019t care about what\u2019s going on under the hood.<\/strong> A big part of UX is keeping a user in familiar territory and reassuring him or her that the app is working properly. The user\u2019s confidence that the refresh happened trumps its technical representation. In our updated pull to refresh, if an update takes longer than 400ms, it will continue to spin until the data is available. <\/p>\n<p>I think you\u2019ll agree, the end result is a pull to refresh that\u2019s enjoyable to use and communicates its function clearly. I really enjoyed going into this level of critical thinking on just one component. It\u2019s a standard to which I\u2019m proud to say we hold ourselves with every new Ionic feature. <\/p>\n<p>Check out what we did <a href=\"https:\/\/github.com\/driftyco\/ionic\/commit\/db27fb116cd3139b271cf9d20c462fb3746f25df\">under the hood on GitHub<\/a>, or take a look at how to add it into your app from our <a href=\"http:\/\/ionicframework.com\/docs\/api\/directive\/ionRefresher\/\">Docs<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For a while now, we\u2019ve wanted to update Pull To Refresh in Ionic. It worked, but it wasn\u2019t exciting, and since it\u2019s a goal of ours at Ionic to make every component as enjoyable to use as it can be, we decided it was time for a change. Here&#8217;s some of the lessons in semiotics [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"","publish_post_category":"","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"","discourse_permalink":"","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[3],"class_list":["post-143","post","type-post","status-publish","format-standard","hentry","category-all","tag-ionic"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Refreshing our Pull-to-Refresh - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Refreshing our Pull-to-Refresh\" \/>\n<meta property=\"og:description\" content=\"For a while now, we\u2019ve wanted to update Pull To Refresh in Ionic. It worked, but it wasn\u2019t exciting, and since it\u2019s a goal of ours at Ionic to make every component as enjoyable to use as it can be, we decided it was time for a change. Here&#8217;s some of the lessons in semiotics [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-09-25T01:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-01-09T06:50:11+00:00\" \/>\n<meta name=\"author\" content=\"Perry Govier\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@perrygovier\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Perry Govier\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\"},\"author\":{\"name\":\"Perry Govier\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/334835947923089c1454927a5a38f23f\"},\"headline\":\"Refreshing our Pull-to-Refresh\",\"datePublished\":\"2014-09-25T01:00:00+00:00\",\"dateModified\":\"2017-01-09T06:50:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\"},\"wordCount\":573,\"commentCount\":18,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"keywords\":[\"Ionic\"],\"articleSection\":[\"All\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\",\"url\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\",\"name\":\"Refreshing our Pull-to-Refresh - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"datePublished\":\"2014-09-25T01:00:00+00:00\",\"dateModified\":\"2017-01-09T06:50:11+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Refreshing our Pull-to-Refresh\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/334835947923089c1454927a5a38f23f\",\"name\":\"Perry Govier\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3fd01a6c7ec7e28809878ae870bceb183d966805efea46bc5ff6ec99493c2eab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3fd01a6c7ec7e28809878ae870bceb183d966805efea46bc5ff6ec99493c2eab?s=96&d=mm&r=g\",\"caption\":\"Perry Govier\"},\"sameAs\":[\"https:\/\/twitter.com\/perrygovier\",\"https:\/\/x.com\/perrygovier\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/perry\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Refreshing our Pull-to-Refresh - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh","og_locale":"en_US","og_type":"article","og_title":"Refreshing our Pull-to-Refresh","og_description":"For a while now, we\u2019ve wanted to update Pull To Refresh in Ionic. It worked, but it wasn\u2019t exciting, and since it\u2019s a goal of ours at Ionic to make every component as enjoyable to use as it can be, we decided it was time for a change. Here&#8217;s some of the lessons in semiotics [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh","og_site_name":"Ionic Blog","article_published_time":"2014-09-25T01:00:00+00:00","article_modified_time":"2017-01-09T06:50:11+00:00","author":"Perry Govier","twitter_card":"summary_large_image","twitter_creator":"@perrygovier","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Perry Govier","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh"},"author":{"name":"Perry Govier","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/334835947923089c1454927a5a38f23f"},"headline":"Refreshing our Pull-to-Refresh","datePublished":"2014-09-25T01:00:00+00:00","dateModified":"2017-01-09T06:50:11+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh"},"wordCount":573,"commentCount":18,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"keywords":["Ionic"],"articleSection":["All"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh","url":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh","name":"Refreshing our Pull-to-Refresh - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"datePublished":"2014-09-25T01:00:00+00:00","dateModified":"2017-01-09T06:50:11+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/refreshing-pull-to-refresh#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Refreshing our Pull-to-Refresh"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/334835947923089c1454927a5a38f23f","name":"Perry Govier","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/3fd01a6c7ec7e28809878ae870bceb183d966805efea46bc5ff6ec99493c2eab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3fd01a6c7ec7e28809878ae870bceb183d966805efea46bc5ff6ec99493c2eab?s=96&d=mm&r=g","caption":"Perry Govier"},"sameAs":["https:\/\/twitter.com\/perrygovier","https:\/\/x.com\/perrygovier"],"url":"https:\/\/ionic.io\/blog\/author\/perry"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=143"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/143\/revisions"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}