diff --git a/_data/content.yml b/_data/content.yml
index 02a3679f9..de41b01f9 100644
--- a/_data/content.yml
+++ b/_data/content.yml
@@ -2,7 +2,6 @@ home:
title: "Rico's cheatsheets"
tagline: |
Hey! I'm @rstacruz and this is a modest collection of cheatsheets I've written.
- (This used to be ricostacruz.com/cheatsheets but now we have a shorter URL!)
top_nav:
title: Devhints.io
@@ -40,3 +39,9 @@ not_found:
title: Not found
description: Sorry, we don't have a cheatsheet for this yet. Try searching!
home: Back to home
+
+announcement:
+ id: 2017-09-25-devhints-io
+ title: New URL 🎉
+ body: |
+ Hey, ricostacruz.com/cheatsheets is moving to devhints.io! Same content with a shorter and easier to remember URL.
diff --git a/_includes/2017/announcements-list.html b/_includes/2017/announcements-list.html
new file mode 100644
index 000000000..9e9711f52
--- /dev/null
+++ b/_includes/2017/announcements-list.html
@@ -0,0 +1,10 @@
+{% if site.data.content.announcement %}
+
+
+
{{ site.data.content.announcement.title }}
+
{{ site.data.content.announcement.body }}
+
+
+
+{% endif %}
+
diff --git a/_layouts/2017/home.html b/_layouts/2017/home.html
index 3f78dc9b9..0ce1182e1 100644
--- a/_layouts/2017/home.html
+++ b/_layouts/2017/home.html
@@ -71,4 +71,6 @@
+{% include 2017/announcements-list.html %}
+
{% include 2017/foot.html %}
diff --git a/_sass/2017/components/announcements-item.scss b/_sass/2017/components/announcements-item.scss
new file mode 100644
index 000000000..830d3dac0
--- /dev/null
+++ b/_sass/2017/components/announcements-item.scss
@@ -0,0 +1,78 @@
+.announcements-list {
+ & {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ max-width: 420px;
+ padding: 0;
+ }
+
+ @media (min-width: 481px) {
+ padding: 16px;
+ }
+
+ @media (min-width: 769px) {
+ padding: 32px;
+ }
+}
+
+.announcements-item {
+ & {
+ position: relative;
+ padding: 16px;
+ box-shadow: $shadow6;
+ border-radius: 1px;
+ background: white;
+ padding-right: 48px;
+ animation: announcements-item-flyin 500ms ease-out;
+ transition: opacity 500ms linear, transform 500ms ease-out;
+ }
+
+ &.-hide {
+ display: none;
+ }
+
+ & > .title {
+ @include font-size(1);
+ font-weight: normal;
+ color: $base-a;
+ margin: 0;
+ padding: 0;
+ }
+
+ & > .close {
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 40px;
+ height: 40px;
+ line-height: 40px;
+ text-align: center;
+ border: 0;
+ margin: 0;
+ padding: 0;
+ cursor: pointer;
+
+ &:hover,
+ &:focus {
+ color: $base-a;
+ }
+ }
+
+ & > .close::before {
+ content: "\00D7";
+ font-size: 14px;
+ }
+}
+
+@keyframes announcements-item-flyin {
+ 0% {
+ transform: translate3d(0, 32px, 0);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translate3d(0, 0, 0);
+ opacity: 1;
+ }
+}
diff --git a/_sass/2017/style.scss b/_sass/2017/style.scss
index 751beddcf..b83e2327d 100644
--- a/_sass/2017/style.scss
+++ b/_sass/2017/style.scss
@@ -19,6 +19,7 @@
@import './markdown/table';
@import './markdown/ul';
@import './components/attribute-peg';
+@import './components/announcements-item';
@import './components/back-button';
@import './components/body-area';
@import './components/code-sponsor';
diff --git a/assets/2017/script.js b/assets/2017/script.js
index 790607e4b..1ab01e9ea 100644
--- a/assets/2017/script.js
+++ b/assets/2017/script.js
@@ -115,6 +115,71 @@ $(function () {
})
})
+/*
+ * Behavior: dismiss button
+ */
+
+$(function () {
+ $('[data-js-dismiss]').each(function () {
+ var $button = $(this)
+ var $parent = $button.closest('[data-js-dismissable]')
+ var id = $parent.data('js-dismissable').id || ''
+
+ $button.on('click', function (e) {
+ Dismiss.setDismissed(id)
+ e.preventDefault()
+ $parent.remove()
+ })
+ })
+
+ $('[data-js-dismissable]').each(function () {
+ var $this = $(this)
+ var id = $this.data('js-dismissable').id || ''
+ const isDismissed = Dismiss.isDismissed(id)
+ if (isDismissed || window.location.search.indexOf('preview') !== -1) {
+ $this.remove()
+ } else {
+ $this.removeClass('-hide')
+ }
+ })
+})
+
+/*
+ * Helper: dismissed
+ */
+
+const Dismiss = {
+ setDismissed: function (id) {
+ Store.update('dismissed', function (data) {
+ data[id] = true
+ return data
+ })
+ },
+
+ isDismissed: function (id) {
+ const data = Store.fetch('dismissed')
+ return data && data[id]
+ }
+}
+
+/*
+ * Simple LocalStorage shim
+ */
+
+const Store = {
+ update: function (key, fn) {
+ if (!window.localStorage) return
+ let data = JSON.parse(window.localStorage[key] || '{}')
+ data = fn(data)
+ window.localStorage[key] = JSON.stringify(data)
+ },
+
+ fetch: function (key) {
+ if (!window.localStorage) return
+ return JSON.parse(window.localStorage[key] || '{}')
+ }
+}
+
/*
* Helper: injects disqus
*/