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

Build flexible and accessible accordion component #11087

Merged
merged 30 commits into from
Sep 21, 2023
Merged

Build flexible and accessible accordion component #11087

merged 30 commits into from
Sep 21, 2023

Conversation

AllanOXDi
Copy link
Member

@AllanOXDi AllanOXDi commented Aug 10, 2023

Summary

This PR creates a flexible and accessible accordion component to support the enhance quiz managment feature .

closes #11011

References

#11011

Reviewer guidance

See the figma design here

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

@github-actions github-actions bot added APP: Coach Re: Coach App (lessons, quizzes, groups, reports, etc.) SIZE: large labels Aug 10, 2023
@AllanOXDi AllanOXDi changed the title Add accordion Build flexible and accessible accordion component Aug 10, 2023
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.

I did some keyboard nav testing and it seems like it's working relatively well, but perhaps we ought to be sure that we're showing the outline on the heading for the AccordionItem.

Currently, the highlight will go from Checkbox to invisible then on to the arrow KIconButton, then to the next row. Looking at the w3 example it appears that the text that would be read by a screen reader ought to also be outlined/highlighted.

Overall - this is excellent work. I know that things get squirrely with the slots and you've got things hooked up very well here. Thank you for your patience working through it all! Look forward to wrapping it up together next week.

(PS I think you need to rebase on develop to resolve the conflicts)

},
data() {
return {
itemIds: [],
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we ought to call this expandedItemIds to make clear what we're tracking here

Comment on lines 59 to 35
if (this.itemIds.includes(id)) {
return true;
} else {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

Non-blocking style note - you can also just be return this.itemIds.includes(id) since you're returning a Boolean here.

Comment on lines 65 to 75
isOptionSelected(optionId) {
const index = this.itemIds.indexOf(optionId);
if (index === -1) {
this.optionsIdList.push(optionId);
} else {
this.optionsIdList.splice(optionId);
}
},
isAnswerSelected(optionId) {
if (this.optionsIdList.includes(optionId)) {
return true;
} else {
return false;
}
},
Copy link
Member

Choose a reason for hiding this comment

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

This kind of logic should live outside of the Accordion altogether. Not all uses of the Accordion will have the check boxes. This is something that will need to be managed by whatever component is making use of the Accordion.


<template
v-if="isItemExpanded(item.id)"
#content=""
Copy link
Member

Choose a reason for hiding this comment

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

No need for the ="" here - this is just to indicate what slot the wrapped content will go into in the parent component

Comment on lines 206 to 251
<AnswerOption
v-for="answer in item.placeholderAnswers"
:key="answer.id"
:optionId="answer.id"
:isOptionSelected="isOptionSelected"
:isAnswerSelected="isAnswerSelected(answer.id)"
>
Copy link
Member

Choose a reason for hiding this comment

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

I'm sorry I wasn't clear about this - but the question editing business is not necessary here. We won't be doing any kind of question editing in this pass, so this PR just needs to have the accordion component ready to be fleshed out in a follow-up which will wire up everything in #11088 to here, rendering the questions we get from the DB

@github-actions github-actions bot added APP: Learn Re: Learn App (content, quizzes, lessons, etc.) DEV: dev-ops Continuous integration & deployment DEV: backend Python, databases, networking, filesystem... APP: Setup Wizard Re: Setup Wizard (facility import, superuser creation, settings, etc.) SIZE: medium and removed DEV: dev-ops Continuous integration & deployment DEV: backend Python, databases, networking, filesystem... APP: Setup Wizard Re: Setup Wizard (facility import, superuser creation, settings, etc.) APP: Learn Re: Learn App (content, quizzes, lessons, etc.) labels Aug 21, 2023
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.

Thanks for the continued efforts here. I've left a few comments about some Kolibri CSS conventions.

I also added some more complex notes around the a11y for the keyboard focus and how we manage clicks, drags, toggles, etc.

<KGrid class="question-row">
<KGridItem :layout12="{ span: 6 }">
<div class="left-column-alignment-style">
<DragHandle>
Copy link
Member

Choose a reason for hiding this comment

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

One thing I noticed is that this doesn't show the cursor when hovered over. I think we should probably update the DragHandle component directly so that it has CSS with pointer: cursor so that we get the hand/pointer rather than the normal mouse arrow.

Copy link
Member

Choose a reason for hiding this comment

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

Additionally - the DragHandle doesn't get a focus outline on it when it is focused.

Take a look at kolibri/plugins/learn/assets/src/views/HybridLearningLessonCard.vue LINE 9/10ish for an example of how the $coreOutline styles can be applied to a component.

@@ -223,4 +444,55 @@
text-align: left;
}

.left-column-alignment-style {
display: inline-flex;
margin-left: 35px;
Copy link
Member

@nucleogenesis nucleogenesis Aug 23, 2023

Choose a reason for hiding this comment

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

We typically try to keep our spacing units in measures of 8px and suggest using em where 1em = 16px as a rule of thumb. So typically we should see values like 0.5em, 1em, 1.5em, etc.

I was looking here because I think the DragHandle should have a bit more space between it and the content to the right of it, so two things to note here:

  • Convert uses of px to the em value OR to a px value that is a multiple of 8px
  • Ensure that there is enough space between the DragHandle and the content so that there is no overlap of the keyboard-mode outline

Comment on lines 130 to 131
<div
v-for="item in placeholderList"
:key="item.id"
>
Copy link
Member

Choose a reason for hiding this comment

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

One thing that came to mind while testing was whether or not keyboard nav focus should cycle through each piece to get to the > KIconButton to open it so I went and tested the W3 example and noticed that the focus flow goes like:

w3accordionkeyboardnav.mp4

However, ours instead of highlighting the whole "header" bit, goes into the children of the row (drag handle -> checkbox -> open/close icon).

Our situation is a bit different because we have interactions within the heading (drag/checkbox) whereas the example above only has text.

This is a little bit of a pickle... because we also want clicking anywhere on the header to toggle open/close and not just the iconbutton - in fact, I think that that KIconButton should really just be a KIcon. BUT the issue might be in that when you click to select a KCheckbox, you'll also end up clicking to trigger the toggle open/close.

For follow up here I think that maybe the next step is to test out what a @click handler here might work okay without getting triggered while clicking the drag handle or KCheckbox. We may need to make some decisions based on how that goes. I'll be happy to cohack a bit on this with you as well to see what we can work out.

Comment on lines 172 to 184
<KIconButton
v-if="isItemExpanded(item.id)"
class="icon-size"
icon="chevronUp"
@click="toggleItemState(item.id)"
/>

<KIconButton
v-else
class="icon-size"
icon="chevronRight"
@click="toggleItemState(item.id)"
/>
Copy link
Member

Choose a reason for hiding this comment

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

As noted above - these probably ought to be KIcons assuming we can get everything jiving well w/ focusing/clicking the whole heading element for toggling.

Copy link
Member

Choose a reason for hiding this comment

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

On a separate note I believe KIconButton adds some padding to the icon so you'll probably need to adjust some margin/padding business to align the KIcon here


<hr class="bottom-border">
<KButton
style="width:100%;margin-bottom:10px"
Copy link
Member

Choose a reason for hiding this comment

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

My note elsewhere re: typically using 8px increments should also be applied to inline styles in the templates

@radinamatic
Copy link
Member

radinamatic commented Sep 1, 2023

It was a bit difficult for me to comment on a single extracted line of code, but I was able to run this branch in development, and actually test some keyboard navigation 😅

Knowing that this is still work in progress, we could maybe postpone resolving all the green ❔ in the recording that indicate that the Tab key press focused an element somewhere, but there's no indication in the UI what is in focus. More important is the fact that Enter or Space key presses when the dragging button (the first element in each accordion item) is in focus should not open the accordion panel (marked as ❌ in the recording), only Enter or Space key presses on the accordion header button (which gets the correct focus outline, yey!!! 🎉) should result in displaying the content of the panel.

EQ2.mp4

Regarding the missing labels for all the dragging buttons and checkboxes for selection, I already suggested some labels in Slack. This below would be my skeleton version of 2 accordion items, one opened the other closed, sort of a stripped down chimera between the implementation here, and the example on the ARIA APG accordion example. If we add a visually hidden span with additional context, we can use the aria-labelledby which supports the concatenation, to improve the element naming for the screen reader users.

<div class="accordion">

  <button type="button" tabindex="0" class="drag-icon icon-size button" aria-label="Move 'question 1' question"></button>

  <! -- logic for keyboard navigable moving/dragging actions ? --> 

  <input type="checkbox" class="k-checkbox-input" aria-label="Select 'question 1' question">

      <span id=question-title-context class="visuallyhidden">
        Open to review and edit
      </span>

  <h3>
    <button type="button"
            aria-expanded="true"
            class="remove-button-style"
            aria-controls="sect1"
            id="accordion1id"
            aria-labelledby="question-title1 question-title-context">
      <span id=question-title1 class="accordion-title">
        question 1
      </span>

      <svg class="icon-size toggle-icon"></svg>
    </button>
  </h3>

  <div id="sect1"
       aria-labelledby="accordion1id"
       class="accordion-detail-container">

       <! -- content of the question 1 --> 

  </div>

  <button type="button" tabindex="0" class="drag-icon icon-size button" aria-label="Move 'question 2' question"></button>

  <! -- logic for keyboard navigable moving/dragging actions ? --> 

  <input type="checkbox" class="k-checkbox-input" aria-label="Select 'question 2' question">

   <h3>
    <button type="button"
            aria-expanded="false"
            class="remove-button-style"
            aria-controls="sect2"
            id="accordion2id"
            aria-labelledby="question-title2 question-title-context">
      <span id=question-title2 class="accordion-title">
        question 2
      </span>
      <svg class="icon-size toggle-icon"></svg>
    </button>
  </h3>

  <div id="sect2"
       aria-labelledby="accordion2id"
       class="accordion-detail-container">

       <! -- content of the question 2 --> 

  </div>

  <! -- the rest of the questions --> 

</div>

@radinamatic
Copy link
Member

radinamatic commented Sep 1, 2023

I would also suggest we disable the dragging with the mouse of accordion items when opened, and enable it only while collapsed. Mostly because questions are bound to have several answers which require panels of certain height, and dragging those elements with a mouse can be a challenge when opened.

@radinamatic
Copy link
Member

I forgot to add mention for @tomiwaoLE to hear his thoughts about the above ⏫

And I'm also thinking that maybe hearing Open to review and edit is a bit too verbose after every question title... 🤔
Since we already have the string Open in the code base, maybe we could just concatenate that with the title?

@tomiwaoLE
Copy link
Member

@radinamatic I'm happy with disabling dragging open question accordions, and enabling only while collapsed.

@nucleogenesis
Copy link
Member

@radinamatic I'm happy with disabling dragging open question accordions, and enabling only while collapsed.

Noting after a chat we've decided to try two approaches:

  1. When clicking the drag-handle of an open item, close the item, then begin dragging.
  2. If that doesn't work, then we will go with just using the up/down icon buttons and will ensure they are accessible.

@nucleogenesis
Copy link
Member

but there's no indication in the UI what is in focus. More important is the fact that Enter or Space key presses when the dragging button (the first element in each accordion item) is in focus should not open the accordion panel (marked as ❌ in the recording),

Also - one thing to note here is that we should be using the arrows instead of the dragging handle whenever we're in the keyboard modality.

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.

@AllanOXDi I've added some thoughts on how possibly to resolve some open issues and clarified some outcomes of discussions re: the drag/sort functionality.

:isLast="index === placeholderList.length - 1"
@moveUp="shiftOne(index, -1)"
@moveDown="shiftOne(index, +1)"
@click.prevent="toggleItemState(item.id)"
Copy link
Member

Choose a reason for hiding this comment

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

I think this is the source of one issue noted by @radinamatic -- this should be triggering the updating of the order of the items, but not toggling the item state. The "toggleItemState" should isntead be on a button that wraps the whole row (I think the button below around line 210 or so).

See the RearrangeChannelsPage for an example; there the @sort event is emitted by the DragContainer where the new order of the items is handled.

Copy link
Member

Choose a reason for hiding this comment

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

Also - I'm having an issue where the drag handle is the only thing being dragged :-/ not sure exactly where the cause of this is by looking at it; but perhaps handling that @sort event will resolve it.

<button
:id="item.id"
:aria-controls="item.id"
aria-expanded="true"
Copy link
Member

Choose a reason for hiding this comment

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

The value here should be :aria-expanded="isItemExpanded(item.id)".

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.

Excellent work here Allan. With the feedback above addressed this is ready to merge

@AllanOXDi AllanOXDi merged commit 17c7368 into learningequality:develop Sep 21, 2023
@AllanOXDi AllanOXDi deleted the add_accordion branch October 2, 2023 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
APP: Coach Re: Coach App (lessons, quizzes, groups, reports, etc.) SIZE: large SIZE: medium SIZE: very large
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants