From 6bc0c55000c13fad118d919ffa0ab2f1c4514064 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 7 Jul 2024 19:05:48 -0700 Subject: [PATCH] Use our hanger loading spinner for the new item page previews It's back, wowie! Also written up in a bit of a component-y way. Cute! --- .../application/hanger-spinner.css | 68 +++++++++++++++++++ app/assets/stylesheets/items/_show.sass | 10 ++- app/views/application/_hanger_spinner.html | 6 ++ app/views/items/_outfit_viewer.html.haml | 1 + app/views/items/show.html.haml | 3 + 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 app/assets/stylesheets/application/hanger-spinner.css create mode 100644 app/views/application/_hanger_spinner.html diff --git a/app/assets/stylesheets/application/hanger-spinner.css b/app/assets/stylesheets/application/hanger-spinner.css new file mode 100644 index 00000000..f52085b0 --- /dev/null +++ b/app/assets/stylesheets/application/hanger-spinner.css @@ -0,0 +1,68 @@ +.hanger-spinner { + position: absolute; + bottom: 8px; + right: 12px; + + height: 32px; + width: 32px; + + @media (prefers-reduced-motion: no-preference) { + animation: 1.2s infinite hanger-spinner-swing; + transform-origin: top center; + } + + @media (prefers-reduced-motion: reduce) { + animation: 1.6s infinite hanger-spinner-fade-pulse; + } +} + +/* + Adapted from animate.css "swing". We spend 75% of the time swinging, + then 25% of the time pausing before the next loop. + + We use this animation for folks who are okay with dizzy-ish motion. + For reduced motion, we use a pulse-fade instead. +*/ +@keyframes hanger-spinner-swing { + 15% { + transform: rotate3d(0, 0, 1, 15deg); + } + + 30% { + transform: rotate3d(0, 0, 1, -10deg); + } + + 45% { + transform: rotate3d(0, 0, 1, 5deg); + } + + 60% { + transform: rotate3d(0, 0, 1, -5deg); + } + + 75% { + transform: rotate3d(0, 0, 1, 0deg); + } + + 100% { + transform: rotate3d(0, 0, 1, 0deg); + } +} + +/* + A homebrew fade-pulse animation. We use this for folks who don't + like motion. It's an important accessibility thing! +*/ +@keyframes hanger-spinner-fade-pulse { + 0% { + opacity: 0.2; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0.2; + } +} diff --git a/app/assets/stylesheets/items/_show.sass b/app/assets/stylesheets/items/_show.sass index 79f6791b..1939fb0b 100644 --- a/app/assets/stylesheets/items/_show.sass +++ b/app/assets/stylesheets/items/_show.sass @@ -58,8 +58,16 @@ body.items-show width: 100% height: 100% + .hanger-spinner + opacity: 0 + transition: opacity .5s + + // When loading, fade in the loading spinner after a brief delay. (We only + // apply the delay here, because fading *out* on load should be instant.) &:has(outfit-layer:state(loading)) - background: gray + .hanger-spinner + opacity: 1 + transition-delay: 2s &:has(outfit-layer:state(error)) border-color: $error-border-color diff --git a/app/views/application/_hanger_spinner.html b/app/views/application/_hanger_spinner.html new file mode 100644 index 00000000..dc3ad717 --- /dev/null +++ b/app/views/application/_hanger_spinner.html @@ -0,0 +1,6 @@ + + + diff --git a/app/views/items/_outfit_viewer.html.haml b/app/views/items/_outfit_viewer.html.haml index 09f76c81..790fdb7a 100644 --- a/app/views/items/_outfit_viewer.html.haml +++ b/app/views/items/_outfit_viewer.html.haml @@ -1,4 +1,5 @@ .outfit-viewer + = render partial: "hanger_spinner" - outfit.visible_layers.each do |swf_asset| %outfit-layer{ data: { diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 92b0d75b..501d9328 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -39,6 +39,9 @@ %li= link_to(contributor.name, user_contributions_path(contributor)) + format_contribution_count(count) %footer= t '.contributors.footer' +- content_for :stylesheets do + = stylesheet_link_tag "application/hanger-spinner" + - content_for :javascripts do = javascript_include_tag "lib/idiomorph", async: true = javascript_include_tag "outfit-viewer", async: true