Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor bookmarks cards #8461

Conversation

marcellamaki
Copy link
Member

Summary

This PR updates some of UI element conflicts that surfaced during string freeze on the Learner bookmarks page, with the main changes being:

  • The cards used on the bookmarks page are now responsive, with mobile-specific layouts
  • Slightly updated "no bookmarks" page
  • Basic tests added for bookmarking

Notes (out of scope)

  • The "remove from bookmarks" feature works, but the "view information" to open the side panel is not included in this PR since that work is still in progress.
  • After refactoring, I have not applied all of the card changes to the channel browsing. It doesn't break things horribly, but that work is also not included as part of this PR

References

Figma specs

No bookmarks

Screen Shot 2021-09-23 at 10 53 33 AM

Desktop view

Screen Shot 2021-09-23 at 11 02 26 AM

Note: the channel thumbnail is going to be added as new metadata, so it is not visible yet and you just see the alt text (and relatedly, the channel title is not yet added, so the title is not being added to the alt text as of yet)

Various mobile previews (Chrome dev tools)

Screen Shot 2021-09-23 at 11 02 56 AM

Screen Shot 2021-09-23 at 11 02 45 AM

Reviewer guidance

  • As these are mostly UI changes, there are not many interactions to test (other than removing a bookmark)
  • I would most appreciate feedback in terms of making the code more readable or suggestions of how to refactor or simplify some of it
  • I'd also love feedback about if I am using KDS theming correctly, and if there are places where I should be using theme tokens where I have hardcoded values (just because...I am not sure if I know what all of the tokens I might use are, honestly)
  • Relatedly, some places where it might be useful to have slightly more dynamic css and fewer specific pixel values (not KDS, but maybe moving some of this into styles={} or setting values in computed.
  • How does this look from a design point of view? What adjustments are still needed? (I am most specifically noting the mobile thumbnails, but am planning to swap out with @MisRob's work on the new if that seems like a better option)
  • I updated some of the values in ContentCard/card.scss - is this going to cause a conflict elsewhere?
  • Test suggestions/guidance always very welcome 🙏

Testing checklist

  • Contributor has fully tested the PR manually
  • If there are any front-end changes, before/after screenshots are included
  • Critical user journeys are covered by Gherkin stories
  • Critical and brittle code paths are covered by unit tests

PR process

  • PR has the correct target branch and milestone
  • PR has 'needs review' or 'work-in-progress' label
  • If PR is ready for review, a reviewer has been added. (Don't use 'Assignees')
  • If this is an important user-facing change, PR or related issue has a 'changelog' label
  • If this includes an internal dependency change, a link to the diff is provided

Reviewer checklist

  • Automated test coverage is satisfactory
  • PR is fully functional
  • PR has been tested for accessibility regressions
  • External dependency files were updated if necessary (yarn and pip)
  • Documentation is updated
  • Contributor is in AUTHORS.md

Copy link
Contributor

@indirectlylit indirectlylit left a comment

Choose a reason for hiding this comment

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

Will review the code, but first two quick design questions - cc @jtamiace

Icon buttons

It's rare in Kolibri (versus Studio) to use purely icon buttons rather than text-based so I wanted to make sure this was intentional. This is partly because learners on tablets don't have tooltips, and partly because learners are less likely to know iconography conventions in contrast to Studio where we use icon buttons more liberally for "power users".

deletion in bookmarks deletion in coach UI
image image

If we do stick with icon buttons, note that we might be using the wrong one for 'delete':

Empty states

We've made 'empty states' more consistent, and I think this design deviates slightly from previous directions:

I would have expected it to look more like:

image

Perhaps something to track in KDS?

@jtamiace
Copy link
Contributor

We should probably go with your suggestion for the empty state.

I'm not too worried about the icon button for removing the bookmark because it's used in the Learn interface for closing out of content and quiz renderers, so hopefully already an association with "making this go away." There's also a way to confirm what it does when they interact with it, and an undo action that if it was unintentional.

Screen Shot 2021-09-24 at 1 58 23 PM

},
},
created() {
ContentNodeResource.fetchBookmarks({ params: { limit: 25 } }).then(data => {
this.more = data.more;
this.bookmarks = data.results;
this.bookmarks = data.results.map(normalizeContentNode);
Copy link
Member

Choose a reason for hiding this comment

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

Although it's possible that API returns an empty array in data.results and therefore map won't fail even when there are no bookmarks, I'd suggest adding a guard to check if data.results are truthy before trying to use map just in case it was undefined or null, just to be sure. Something like

this.bookmarks = data.results ? data.results.map(normalizeContentNode) : []

text-align: center;
}

.bookmarks-header {
Copy link
Member

@MisRob MisRob Sep 27, 2021

Choose a reason for hiding this comment

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

I am not sure how this would look like here on this page and am using this style only as a good example so @marcellamaki no changes may be needed here if results are not acceptable at this point.

Generally speaking, I'd rather use h1 as is without this style even though it might mean that it won't be pixel perfect, and then eventually update our global styles for fonts, maybe even using a system based on rem units. For this reason, I've been trying to avoid updating font styles in hybrid learning work unless it looked really necessary. I am afraid that otherwise, this approach would lead to styling titles and texts on each page separately and will tend to end up with many inconsistencies across the whole app.

My suggestion would be to ignore tweaking fonts altogether (unless something looks very horrible without doing so) and having a GitHub issue for texts styles. I am not sure though about how our current system works and if changes to it could lead to problems in parts of the app that don't have this new hybrid learning look so we could also use that issue to think through this.

@indirectlylit @jtamiace any thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree - didn't realize the header was a different style than other headers in the app. Plain h1 would be better for consistency, and I don't see a reason why the header on this page needs to be different than the others.

Copy link
Member

Choose a reason for hiding this comment

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

+1 for universal styles in typography. I feel like this should live in KDS both as guidance and as some sort of CSS or SCSS mixins that we can use to define consistent cross-product styles.

@MisRob
Copy link
Member

MisRob commented Sep 27, 2021

Are the left and right margins on one of your screenshots intentional?
Screenshot from 2021-09-27 07-05-37

Designs have the same left and right margin as the top margin (24px): https://www.figma.com/file/uiZuCIqh2KYvBUfbCiJyyA/Hybrid-Learning?node-id=130%3A11752

@MisRob
Copy link
Member

MisRob commented Sep 27, 2021

I updated some of the values in ContentCard/card.scss - is this going to cause a conflict elsewhere?

I'd say that no one can say for sure so I'd suggest checking all places where ContentCard is used to see if there is some before/after difference. If not, no problem I guess :) If yes, then it's something to be included in the PR description (that's one of the purposes of "If there are any front-end changes, before/after screenshots are included" in the PR checklist - it's not only for screenshots of new features but also for checking regressions)

If there are some regressions, we'll need to have a look if that particular part of the app is going to be refactored into hybrid learning overcoat before the next release or no and based on that, decide if we need to adjust ContentCard with some props or even having two separate cards components.

(I am most specifically noting the mobile thumbnails, but am planning to swap out with @MisRob's work on the new if that seems like a better option)

I'd say this is the same question. It'd be ideal to use (and adjust if needed) our new thumbnails that were made for hybrid learning in general (learn/assets/src/views/thumbnails), however, I am not sure if it's welcome in all places where ContentCardListViewItem is currently used. If such an update shows to be complicated, I think it'd be fine to stay with CardThumbnail and follow up on thumbnails later. Seems to be part of a larger issue of having many cards and some of them somewhere in the middle of a migration to hybrid learning, so I wouldn't complicate it now.

:description="content.description"
activityLength="shortActivity"
Copy link
Member

@MisRob MisRob Sep 27, 2021

Choose a reason for hiding this comment

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

Is this a temporary value?

Regarding activity length, there is some logic prepared in LearningActivityLabel . So far it's been used to show duration or its textual representation on the home page. If it'd be useful, feel free to move some of this code from the component somewhere higher in the structure and use it for bookmarks.

return this.createdDate;
},
bookmarkCreated() {
const time = this.$formatRelative(this.ceilingDate, { now: this.now });
Copy link
Member

Choose a reason for hiding this comment

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

Will the time be correct if I have a page with this component open for a couple of minutes and then bookmark something? I haven't tested this myself yet though from what I see in code my guess would be that right now this.now would rather return time when this component was mounted and not necessarily when a bookmark was really created.

Copy link
Member Author

Choose a reason for hiding this comment

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

This card component is used for the bookmarks page itself, and so I am trying to figure out a way where it might be mounted and then have a bookmark created after without a re-navigation. I have tried testing this and so far it seems that the bookmarks time is reflecting accurately. But if you have a specific scenario in mind (or if someone else has one!), I would be happy to give it a try!

Copy link
Member

Choose a reason for hiding this comment

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

Thank you for checking it. From your explanation, it seems that it creates a hidden dependency from where this component is being used so even though things work for the bookmarks page, I'd recommend using something like this removed implementation so that we can be sure that it will work as expected no matter of scenario since this is a general component. Related to that, ContentCardListViewItem is used in ContentCardGroupGrid which seems to be imported into another four pages.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, now I see what you're saying. I will re-add the code for it to work as expected, and I also have in my note today to follow up on the usage of ContentCardListViewItem and the other places ContentCardGroupGrid is used, because I noticed that yesterday when I was working on something else. Thanks Misha!

Copy link
Member

Choose a reason for hiding this comment

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

Sure, and regarding those components being used from both non-hybrid-learning and hybrid-learning, I hope we can find something simple to not block this PR way too much :) Just from the code, those various dependencies look to be "meeeh" :)) Let me know please if I can help with that somehow.

describe('When the user clicks the remove from bookmarks icon', () => {
it('will make a call to remove the bookmark from the list of bookmarks', () => {
wrapper.findComponent({ name: 'ContentCardGroupGrid' }).vm.$emit('removeFromBookmarks');
expect(removeFromBookmarksSpy).toHaveBeenCalled();
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't test if a call was made. If there was an error in removeFromBookmarks method, this test would still pass even though the call wasn't made. That's one of the reasons why it's usually not recommended to test internal methods of components.

I'd recommend mocking client and checking that it's been called with correct method and url parameters.

});
it('clicking the load more button calls the load more function', () => {
wrapper.find("[data-test='load-more-button']").vm.$emit('click');
expect(loadMoreSpy).toHaveBeenCalled();
Copy link
Member

Choose a reason for hiding this comment

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

Similar to the above, checking that some method inside of a component has been called doesn't say much about if things actually work. I'd recommend checking that fetchBookmarks on ContentNodeResource has been called with correct params.

@marcellamaki
Copy link
Member Author

@jtamiace - I am wondering about how to proceed with the thumbnails and card spacing from a design point of view. I'll include a few screenshots below, and please let me know if you have questions.

With the thumbnails, since we have a variety of image ratios, there are some constraints that are used to contain the image (i.e., it shrinks to fit its boundaries, rather than being cropped). This is less noticeable with the list card view, but the top margin of the card is offset, see below:

Screen Shot 2021-09-28 at 10 52 10 AM

(full image container background - and alignment - visible in grey)

Screen Shot 2021-09-28 at 10 51 57 AM

But by keeping the width fixed, the difference in height becomes more noticeable on mobile especially. I can fill the background of the image's container as a light grey (which is something @MisRob has implemented with her new thumbnails work, although I don't think the component will be appropriate to use here but maybe can be added with a larger card refactor) which to me seems to keep the margin feel consistent, since there is a clear separation between "bonus space" of the thumbnail and the white of the margin. It also feels less "crisp" (I can't think of a better word - hopefully you will know what I am trying to get at)...

For example, in some various mobile views:

Without background With grey background
Screen Shot 2021-09-28 at 10 42 57 AM Screen Shot 2021-09-28 at 10 42 36 AM
Screen Shot 2021-09-28 at 10 42 50 AM Screen Shot 2021-09-28 at 10 42 25 AM

So, I guess the question is, which option would you prefer that I use? Also, if @MisRob or @indirectlylit have alternative suggestions of how I might manage this, would be very open to hearing them!

@MisRob
Copy link
Member

MisRob commented Sep 28, 2021

Regarding the thumbnails, as I mentioned above I think it's completely fine to not use the new ContentNodeThumbnail if it's more complicated to use it rather than not for components that are sometimes used for new hybrid learning features and sometimes used for parts that we won't manage to migrate for the new release, if there are such places. However if possible I'd suggest mimicking its behavior as closely as possible - which means showing thumbnails in 16:9 ratio with light gray letterboxing (we agreed on this because 16:9 is the most common ratio) since I assume we'll migrate all cards eventually to render consistent thumbnails, is that right?

Copy link
Member

@nucleogenesis nucleogenesis left a comment

Choose a reason for hiding this comment

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

One additional item to note is that there is some usable whitespace in the mobile cards between the footer & the text. I think maybe an 8px vertical padding on the activity type (the icon & "watch/read/etc" bit) in mobile might give some good spacing between the thumbnail and the activity and the title.

Of course, items with small descriptions or no description are doomed to have some whitespace there, but this example is truncated. Maybe even using the standard font size could make use of the available space naturally without needing.

I quickly tried it out in devtools and a combination of these changes feel to maximize the use of available whitespace (but would need some testing, maybe tweaking for desktop vs mobile).

.metadata-info {
    margin: 8px 0; // This won't look right on desktop though
}

.text {
    /* other .text styles */
    font-size: 16px;
}

image

Comment on lines 73 to 212
.chip-right {
position: absolute;
right: 10px;
bottom: 20px;
height: 34px;
padding: 8px;
font-size: 13px;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 4px;
}

.chip-left {
position: absolute;
bottom: 20px;
left: 10px;
height: 34px;
padding: 8px;
font-size: 13px;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 4px;
}
Copy link
Member

Choose a reason for hiding this comment

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

You don't have to account for both LTR and RTL with CSS classes in this case. We have some magic in our build system that automatically creates those styles. @indirectlylit (I think) may be best to describe how this works.

I just tested it - if you just create one class and style for LTR like so:

.chip {
    left: 10px;
    /* the rest of the styles */
}

Then change your language to Arabic and check the CSS on that chip class and you'll see that the left in your code is a right in the browser.

Copy link
Member

Choose a reason for hiding this comment

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

Separately, and this may be something to discuss in KDS as well, I received early on and have since held closely to the guidance that we should try to work within 8px increments wherever possible, 4 if needed, which is derived to some extent by Material guidelines.

I double checked KDS and see that we don't really have such guidelines, although it would be nice to have some. In any case, it's fairly nitpicky and looks fine as-is in the browser. Would love @indirectlylit and @MisRob 's thoughts w/ regard to whether we should aim to codify some aspect of this guidance in KDS or if it should just be a Kolibri thing (or if we are getting little/no benefit from the long-held norm).

I personally appreciate consistency in the code and have found trying to do everything at 8/16/24/etc px has been pretty painless in most cases.

Copy link
Member

Choose a reason for hiding this comment

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

One last note here is that I think that the height entry is unnecessary, you're expanding the container vertically with padding already and I didn't see any change when I removed it locally.

Copy link
Contributor

Choose a reason for hiding this comment

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

Separately, and this may be something to discuss in KDS as well, I received early on and have since held closely to the guidance that we should try to work within 8px increments wherever possible, 4 if needed, which is derived to some extent by Material guidelines.

I double checked KDS and see that we don't really have such guidelines, although it would be nice to have some. In any case, it's fairly nitpicky and looks fine as-is in the browser. Would love @indirectlylit and @MisRob 's thoughts w/ regard to whether we should aim to codify some aspect of this guidance in KDS or if it should just be a Kolibri thing (or if we are getting little/no benefit from the long-held norm).

I personally appreciate consistency in the code and have found trying to do everything at 8/16/24/etc px has been pretty painless in most cases.

Sorry, just saw this message!

Thanks for flagging this @nucleogenesis. This is in fact already documented in the design system here:

https://design-system.learningequality.org/layout/#spacing

For more context, folks can read about "baseline grids" in the context of Material Design or in general.

Comment on lines 374 to 377
.footer-right {
display: block;
float: left;
}
Copy link
Member

Choose a reason for hiding this comment

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

image

These icons ought to be flipped to the other side but the RTL version puts the icons under the thumbnail.

I'd suggest using flex here instead of floats. I think that floats aren't really supposed to be used for layout and that their primary purpose is to allow elements to flow around something that is stuck to one side.

I think that something like this could work if you remove the footer-left/right styles and classes altogether. I tried it out quickly and seems to work well, but the footerIcons prop will need to be ordered so that the X is the outer-most icon. The flex-end automatically aligns everything to the correct side between RTL/LTR. Then the changes to metadata-info-footer align everything vertically when in mobile.

.footer {                     
  position: absolute;         
  bottom:0;                   
  display: flex;              
  justify-content: flex-end;  
  width: 100%;                
  padding: 16px;                         
}  

.metadata-info-footer {
  flex: auto;          
  align-self: center;  
  margin: 0;           
  font-size: 13px;     
}                               
                           

@marcellamaki
Copy link
Member Author

Updated notes on changes for devs

  • Per conversation several weeks ago with @MisRob and @bjester, I've done some refactoring to make separate "hybrid learning components" so we have greater reassurance that changes made in this PR will not cause regressions, and that any regressions will be known as regressions, rather than causing confusion of "what is in progress or in scope"
  • Ensured thumbnail uses 16:9 ratios with grey in alignment with other thumbnail work
  • Adjusted some spacing and layouts to be more standard using pixel increments per @nucleogenesis, and other layout tweaks based on design guidance and consistent application of KDS principles

Updated QA guidance for @radinamatic and @pcenov (and @jtamiace for design, if so inclined)

Core functionality to test:

While there are a few adjustments that still need to be made to the cards, most of the card UI is "done" and UI/design review can include these points:

  • Cards should correspond to figma
  • Card should render correctly on mobile devices (with the correct mobile layout)
  • Card content (aside from noted bugs) should be accurate
  • Bookmarked timestamp/date should display correctly

NOTES:

Progress/Completion bug weirdness is popping up here too, so the progress bar may or may not be visible, based on what you are looking at! My recommendation right now is to put a pin in that part of the testing 📌

Known TO-DOs are pointed out in the screenshot below (learning activity icon and string is missing and the placeholder is messing up some spacing, channel icon and channel title for alt text missing, activity length is a placeholder 'short activity')
Screen Shot 2021-10-12 at 5 23 09 PM

@marcellamaki marcellamaki changed the base branch from develop to release-v0.15.x October 12, 2021 22:18
@pcenov
Copy link
Member

pcenov commented Oct 13, 2021

Hi @marcellamaki and @radinamatic
I've tested this one today in Win 10 and Ubunto on several browsers + the Android build.
I should be noted that testing was hampered by the great number of known issues and especially the bookmark state carrying over. Also I'm not able to view any of the resources and therefore test the completion progress. The mobile view of the Library page is still a WIP.

Here is the test report:

Functionality Test Result Comment
Display either a selection of bookmarks or the "You have no bookmarked resources" message Pass
Remove a bookmark by clicking the X Fail #8497
Add or remove a bookmark from within the content renderer Pass
Bookmark state incorrectly carrying over between bookmarks Fail The bookmark state is still carrying over
Bookmarked card should correspond to figma Pass aside from noted bugs
Bookmarked card should render correctly on mobile devices Pass --
Bookmarked card content (aside from noted bugs) should be accurate Pass aside from noted bugs
Bookmarked timestamp/date should display correctly Pass --
Progress/Completion Not Tested The feature cannot be tested with this build
RTL display of the bookmarked resources Pass -

@marcellamaki
Copy link
Member Author

Hi @pcenov - thank you for the QA given the challenges of known bugs. I've also realized one last code change I made to fix the icon I didn't push to github, I just had it locally, so I apologize for the oversight and for the difficulty you encountered while testing this. Hopefully as Jacob and I push though this last bit of frontend work and integration in the next two weeks, we will soon have much more complete (and less frustrating) features for you to test!

Copy link
Member

@nucleogenesis nucleogenesis left a comment

Choose a reason for hiding this comment

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

  1. The bug Radina noted in the other PR is not fixed and doesn't feel in scope here (you've not changed the source of the issue). I mentioned this in #hybrid-learning on Slack that I fixed that toggle locally so that I could add bookmarks in order to test being able to delete them properly.

You can see my commit here - it's not fully tested but it let me add bookmarks where I couldn't initially.

Generally, this is coming together great. Looks good, feels good. Just a couple issues outstanding and then should be good to go!

@nucleogenesis
Copy link
Member

@marcellamaki I finally (sorry) just got to get to test this and I'm not seeing any content in channels and the cards in the library page don't do anything so I cannot add any Bookmarks.

I tried rebasing the branch locally but still wasn't seeing any content. If this isn't a known issue resolved elsewhere, I'd hold off on merging before the bug bash.

@marcellamaki
Copy link
Member Author

marcellamaki commented Oct 26, 2021

@nucleogenesis - the issue you describe is a result of me doing a sub-par rebase (things to learn for the future!). It is fixed in the subsequent PR for the Library Page. Obviously now we are not hurrying to get in before the bug bash, so no need to merge quickly, but just as an FYI.

If you're able to access content from the home page, it should open the content renderer correctly. (It is working locally for me on this branch). If that's a feasible workaround for this PR, and you can review what you need, that's great, but if not, just let me know and I can scoot some of the updates to the Library page back into this PR tomorrow so that it's a bit easier to work with.

[ETA: I am just going to pull that code in in the morning so everything is easier to review!]

@marcellamaki
Copy link
Member Author

Superseded by #8548

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
TODO: needs review Waiting for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants