Skip to content

Commit

Permalink
Refactor show-more.jslogic & update documentation.
Browse files Browse the repository at this point in the history
This commit updates the show-more js file which can be used for multiple components that require a fold in/ fold out functionality.

The refactor aims to keep the existing funtionality aswell as add to it. This includes
- Make it possible to select whether the list-button show be visible or not after expanding a list.
- Determine how many list items show be initially shown, with a fallback of the amount of list-elements if not specified.
- Automatically hide the button if there are no more elements to show than specified through the
- Automatically handle aria-control linking between list/button.
- Moved some data-attributes to other elements as well as renaming some variables.

If you see any improvements to something or another feature that would be nice feel free to comment.

Currently it is only possible to use this, if the button/list exists in the same wrapper. This could be change later if relevant but  currently it isn't.

Updated .md file also to reflect these changes.

DDFFORM-69
  • Loading branch information
LasseStaus committed Apr 19, 2024
1 parent 3b14277 commit d819330
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 47 deletions.
84 changes: 58 additions & 26 deletions src/stories/utils/show-more.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,73 @@
document.addEventListener("DOMContentLoaded", () => {
const lists = document.querySelectorAll("[data-show-more-list]");
const listWrappers = document.querySelectorAll(
"[data-show-more-list-wrapper]"
);

lists.forEach((list) => {
const uid = Math.floor(Math.random() * 1000000);
list.setAttribute("id", `category-list-${uid}`);
listWrappers.forEach((listWrapper) => {
const list = listWrapper.querySelector("[data-show-more-list]");
const listId = list.getAttribute("data-show-more-list-id");
const listElements = list.querySelectorAll("[data-show-more-item]");
const amountOfListElements = parseInt(listElements.length, 10);
const listShowMoreButton = listWrapper.querySelector(
"[data-show-more-button]"
);

const categories = list.querySelectorAll("[data-show-more-item]");
const toggleButton = list.querySelector("[data-show-more-button]");
toggleButton.setAttribute("id", `category-toggle-${uid}`);
if (!list || !listShowMoreButton || !listElements || !listId) {
const missingElements = [];
if (!list) missingElements.push("list");
if (!listShowMoreButton) missingElements.push("listShowMoreButton");
if (!listElements.length) missingElements.push("listElements");
if (!listId) missingElements.push("listId");

// eslint-disable-next-line no-console
console.debug(
`show-more.js: Missing required elements: ${missingElements.join(", ")}`
);
return;
}

// Add listId & aria attributes to list and buttons
list.setAttribute("id", `list-id-${listId}`);
listShowMoreButton.setAttribute("aria-controls", `list-id-${listId}`);

const initialVisibleItems =
list.getAttribute("data-show-more-initial-visible-items") || 2; // default to 2 if not set
list.getAttribute("data-initial-visible-items") || amountOfListElements;

// if there are no categories or only one category, hide the toggle button
// or if there are less categories than the initial visible items, hide the toggle button
if (!categories.length || categories.length <= initialVisibleItems) {
toggleButton.classList.add("show-more__hidden");
// Hide button if there are less items than the initial visible items
if (initialVisibleItems >= amountOfListElements) {
listShowMoreButton.classList.add("show-more__hidden");
return;
}

const showMoreText =
toggleButton.getAttribute("data-show-more-text") || "+";
const hideMoreText =
toggleButton.getAttribute("data-show-more-hide-text") || "-";
const visibleItems = initialVisibleItems - 1;

categories.forEach((item, index) => {
if (index > visibleItems) item.classList.add("show-more__hidden");
// Hide items beyond the initial visible items
listElements.forEach((listItem, index) => {
if (index > initialVisibleItems - 1)
listItem.classList.add("show-more__hidden");
});

toggleButton.addEventListener("click", () => {
const isExpanded = toggleButton.getAttribute("aria-expanded") === "true";
categories.forEach((item, index) => {
if (index > visibleItems) item.classList.toggle("show-more__hidden");
const showMoreText = listShowMoreButton.getAttribute("data-show-more-text");
const showLessText = listShowMoreButton.getAttribute("data-show-less-text");
const hideListButtonAfterExpand = list.getAttribute(
"data-hide-list-button-after-expand"
);

listShowMoreButton.addEventListener("click", () => {
listElements.forEach((listItem, index) => {
if (index > initialVisibleItems - 1)
listItem.classList.toggle("show-more__hidden");
});
toggleButton.innerText = isExpanded ? showMoreText : hideMoreText;
toggleButton.setAttribute("aria-expanded", !isExpanded);

const isAriaExpanded =
listShowMoreButton.getAttribute("aria-expanded") === "true";
listShowMoreButton.setAttribute("aria-expanded", !isAriaExpanded);

listShowMoreButton.innerText = isAriaExpanded
? showMoreText
: showLessText;

if (hideListButtonAfterExpand === "true" && !isAriaExpanded) {
listShowMoreButton.classList.add("show-more__hidden");
}
});
});
});
54 changes: 33 additions & 21 deletions src/stories/utils/show-more.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,45 @@ Follow these steps to implement this feature effectively:
Structure your HTML elements as follows for implementing the
"Show More/Less" feature:

- **List Element**:
Use an wrapper element with the `data-show-more-list` attribute
This element will contain both the list items and the toggle button.
- **List wrapper**:
Assign this value to the element that will wrap both the list and the button
associated with the list. Use a wrapper element with the
`data-show-more-list-wrapper` attribute.
- **List**:
Assign this to the list you want to control. Include the following data
attributes for the element:
- `data-show-more-list`: Indicates that this list is controlled by the show
more/less functionality.
- `[data-show-more-list-id`: Indicates a an ID for the list. The ID is used
to set aria-controls on the button to the list, and sets a list-id-X
attribute on the list.
- `data-initial-visible-items`: Specifies the initial number of items visible.
This is optional and defaults to the total number of items if not set.
- `data-hide-list-button-after-expand="true"`: Specifies whether to hide the
button after expanding the list. Add this with value of `true` if you do
not want the button to be displayed after the list is
expanded, otherwise do not add it.
- **List Items**:
Assign the `data-show-more-item` attribute to each list item that you want
to show or hide.
- **Toggle Button**:
Place a button within the list element with the `data-show-more-button`
Place a button within the list element with the data-show-more-button
attribute. This button is used by users to toggle the visibility of list items.
- **ARIA Expanded**:
Add the `aria-expanded="false"` attribute to the button to indicate the current
state (expanded or collapsed) of the additional content.
- **Show More Text (Optional)**:
Use the `data-show-more-text` attribute on the button to specify the text
displayed when there's more content to show.
- **Show Less Text (Optional)**:
Use the `data-show-more-hide-text` attribute on the button to specify the text
displayed when the list is in its collapsed state.
- **Initial Visible Items (Optional)**:
Set the initial number of visible items with the
`data-show-more-initial-visible-items` attribute. It defaults to 2 if not set.
- `data-show-more-text`: Specifies the text displayed on the button when
there are more items to show.
- `data-show-less-text`: Specifies the text displayed on the button when
the list is fully expanded.
- **AARIA Attributes**:
- `aria-expanded`: Add the aria-expanded="false" attribute to the button to
indicate the initial state (expanded or collapsed) of the additional content.
- `aria-controls`: This will be added to the button with a reference to
the list it controls.

### Example HTML Markup

```html
<div data-show-more-list>
<ul>
<div data-show-more-list-wrapper>
<ul data-show-more-list="true" data-initial-visible-items="2" data-hide-list-button-after-expand>
<li data-show-more-item>Item 1</li>
<li data-show-more-item>Item 2</li>
<!-- additional items are hidden by default -->
Expand All @@ -44,12 +56,12 @@ Set the initial number of visible items with the
<button
class="cursor-pointer"
aria-expanded="false"
data-show-more-button
data-show-more-button="true"
data-show-more-text="Show more"
data-show-more-hide-text="Show less"
data-show-more-initial-visible-items="2"
data-show-less-text="Show less"
>
Show more
</button>
</div>

``````

0 comments on commit d819330

Please sign in to comment.