Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

VLogoLoader #448

Merged
merged 18 commits into from
Dec 3, 2021
Merged

VLogoLoader #448

merged 18 commits into from
Dec 3, 2021

Conversation

zackkrida
Copy link
Member

@zackkrida zackkrida commented Nov 25, 2021

Fixes

Fixes #371 by @zackkrida

Description

Adds a new VLogoLoader component and some supporting composables:

  • One for using event listeners (no longer being used, so I could remove)
  • One for using media queries (added by @obulat modified by me)
  • One for using prefers-reduced-motion

The loader itself is an aria-hidden, visual enhancement to the site. It does not have any inherent accessibility qualities, nor is it focusable. Originally I thought this component should be an ARIA Live Region1 but after some research that will be a role better served by our actual search grid, which can announce it's own loading status, the # of newly added results after the user hits the 'load more' button, and so on. I'll make a new ticket soon to spec out those improvements.

Testing Instructions

This component can be tested with npm run storybook and viewing the VLogoLoader story. There are a few things you can do:

  • Toggle the status prop from "loading" to "idle" with the handles
  • Set prefers-reduced-motion in your browser while in the "loading" status, observe the change in animation to a more subtle, non-moving effect. This is currently a gentle pulse from full to partial opacity. @panchovm might have a better idea for a subtle animation that doesn't add movement, but still visually conveys to the user that loading is occurring. Prefers reduced motion !== wants no motion. Here's a quick video on how to test for prefers reduced motion:
CleanShot.2021-12-02.at.19.26.37-converted.mp4

Follow-up questions

  1. Please suggest any test cases I should add. I admittedly don't love unit testing of front-end components and am always looking for improvements there.

  2. The component is extremely small in terms of pixel values in the mockups (cc @panchovm), with the logo being 20px tall with 14px of padding surrounding. This has been increased to 32px tall with 16px of padding in my component. Otherwise the Openverse logo is barely legible, even on my 5k monitor.

    My sizing

    CleanShot 2021-12-02 at 19 55 00@2x

    Figma sizing

    CleanShot 2021-12-02 at 19 54 04@2x CleanShot 2021-12-02 at 19 54 29@2x
  3. The mobile menu includes the logotext "Openverse", I think that can simply exist next to this loader but perhaps be wrapped in the same <NuxtLink /> component.

Checklist

  • My pull request has a descriptive title (not a vague title like Update index.md).
  • My pull request targets the default branch of the repository (main) or a parent feature branch.
  • My commit messages follow best practices.
  • My code follows the established code style of the repository.
  • I added or updated tests for the changes I made (if applicable).
  • I added or updated documentation (if applicable).
  • I tried running the project locally and verified that there are no visible errors.

Developer Certificate of Origin

Developer Certificate of Origin
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

Footnotes

  1. https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions

@zackkrida zackkrida self-assigned this Nov 25, 2021
@zackkrida zackkrida added 🌟 goal: addition Addition of new feature 🕹 aspect: interface Concerns end-users' experience with the software 🟧 priority: high Stalls work on the project or its dependents labels Nov 25, 2021
@zackkrida
Copy link
Member Author

zackkrida commented Dec 1, 2021

Note, the current aria live region implementation is incorrect 😄 but will be revised soon.

Edit: It doesn't exist anymore, and is unnecessary for this component.

@zackkrida zackkrida marked this pull request as ready for review December 3, 2021 01:13
@zackkrida zackkrida requested a review from a team as a code owner December 3, 2021 01:13
@sarayourfriend sarayourfriend self-requested a review December 3, 2021 02:00
@obulat obulat mentioned this pull request Dec 3, 2021
6 tasks
* @param {import('@nuxtjs/composition-api').SetupContext} context
*/
setup() {
const defaultWindow = typeof window !== 'undefined' ? window : undefined
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default window is being used in several places now to ensure that composables work correctly with SSR. Is there a way to extract this code somehow?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it could be the default value in the hook, at least. Not sure if it'll work, I'll test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you can use a default value as it'll try to evaluate window even when it's undefined and throw an error.

Co-authored-by: Olga Bulat <obulat@gmail.com>
Copy link
Contributor

@obulat obulat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Logo loader component is awesome!

Copy link
Member

@krysal krysal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks amazing! You can see the attention to details, really nice ✨

src/components/VLogoLoader/meta/VLogoLoader.stories.js Outdated Show resolved Hide resolved
Co-authored-by: Krystle Salazar <krystle.salazar@automattic.com>
@zackkrida zackkrida added this to the Redesign milestone Dec 3, 2021
Copy link
Contributor

@sarayourfriend sarayourfriend left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! The CSS animations are magic to me 🤩 Just a couple documentation things but otherwise looks great!

With respect to the "pulsing" reduced motion version... I have decent vision and I can barely tell anything is happening. In fact, it might as well not even pulse if it's that subtle.

src/components/VLogoLoader/VLogoLoader.types.js Outdated Show resolved Hide resolved
* @param {import('@nuxtjs/composition-api').SetupContext} context
*/
setup() {
const defaultWindow = typeof window !== 'undefined' ? window : undefined
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you can use a default value as it'll try to evaluate window even when it's undefined and throw an error.

src/composables/use-event-listener.js Outdated Show resolved Hide resolved
Comment on lines +19 to +22
watch(target, (value, oldValue) => {
oldValue?.removeEventListener(event, handler)
value?.addEventListener(event, handler)
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use onInvalidate to remove the event listener?

Suggested change
watch(target, (value, oldValue) => {
oldValue?.removeEventListener(event, handler)
value?.addEventListener(event, handler)
})
watch(target, (value, _, onInvalidate) => {
value?.addEventListener(event, handler)
onInvalidate(() => value?.removeEventListener(event, handler))
})

I'm not 100% sure there is a difference, I'll do some fiddling to test this out, but i think the watcher may never run on component dismount to remove the old listener but invalidate will run.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like your take on it! 😄

Comment on lines +30 to +32
onBeforeUnmount(() => {
unref(target)?.removeEventListener(event, handler)
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, I see, I guess onInvalidate isn't necessary because the clean up happens in one place here?

test/unit/specs/components/v-logo-loader.spec.js Outdated Show resolved Hide resolved
src/composables/use-media-query.js Outdated Show resolved Hide resolved
zackkrida and others added 2 commits December 3, 2021 11:34
Co-authored-by: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com>
Co-authored-by: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com>
@fcoveram
Copy link

fcoveram commented Dec 3, 2021

It looks awesome. Great work.

I agree with @sarayourfriend as the fading effect is not very noticeable. And I would add that it might be unnecessary. The idea of motion reduction is great, but in this case, the animation is very subtle and lives in a context where the skeleton interface fading is more proper for showing the loading instance.

@zackkrida
Copy link
Member Author

@panchovm that's a great point about the skeleton loaders. I think I will go with no animation then!

@zackkrida
Copy link
Member Author

@sarayourfriend Let's follow up on the event listener code testing—it'd be nice to adopt that in more places in the future too.

@zackkrida zackkrida merged commit b8f5a39 into main Dec 3, 2021
@zackkrida zackkrida deleted the v-logo-loader-fix-#371 branch December 3, 2021 17:04
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🕹 aspect: interface Concerns end-users' experience with the software 🌟 goal: addition Addition of new feature 🟧 priority: high Stalls work on the project or its dependents
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Component: Header Logo (VLogoLoader)
5 participants