diff --git a/src/components/list/paginated_list/action_bar/ActionBar.jsx b/src/components/list/paginated_list/action_bar/ActionBar.jsx index 2f6bd054..2657a644 100644 --- a/src/components/list/paginated_list/action_bar/ActionBar.jsx +++ b/src/components/list/paginated_list/action_bar/ActionBar.jsx @@ -4,7 +4,7 @@ import { SearchInput } from "@logora/debate/input/search_input"; import { Select } from "@logora/debate/input/select"; import { Tag } from "@logora/debate/tag/tag"; import cx from "classnames"; -import React, { useState } from "react"; +import React, { useState, useRef, useCallback, useEffect } from "react"; import { useIntl } from "react-intl"; import { useLocation } from "react-router"; import styles from "./ActionBar.module.scss"; @@ -28,6 +28,37 @@ export const ActionBar = ({ const location = useLocation(); const { isMobile } = useResponsive(); const [searchActive, setSearchActive] = useState(false); + const tagContainerRef = useRef(null); + const [tagCanScrollLeft, setTagCanScrollLeft] = useState(false); + const [tagCanScrollRight, setTagCanScrollRight] = useState(false); + + const checkTagScroll = useCallback(() => { + const el = tagContainerRef.current; + if (!el) return; + setTagCanScrollLeft(el.scrollLeft > 1); + setTagCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1); + }, []); + + useEffect(() => { + checkTagScroll(); + const el = tagContainerRef.current; + if (!el) return; + const observer = new ResizeObserver(checkTagScroll); + observer.observe(el); + return () => observer.disconnect(); + }, [orderedTagList, checkTagScroll]); + + const scrollTags = (direction, e) => { + e.stopPropagation(); + const el = tagContainerRef.current; + if (!el) return; + const scrollAmount = 200; + el.scrollBy({ + left: direction === "left" ? -scrollAmount : scrollAmount, + behavior: "smooth", + }); + setTimeout(checkTagScroll, 300); + }; const urlParams = new URLSearchParams( typeof window !== "undefined" ? window.location.search : location.search, ); @@ -154,7 +185,33 @@ export const ActionBar = ({
{subtitle}
)} {orderedTagList.length > 0 && ( -
{orderedTagList.map(displayTags)}
+
+ +
+ {orderedTagList.map(displayTags)} +
+ +
)} )} diff --git a/src/components/list/paginated_list/action_bar/ActionBar.module.scss b/src/components/list/paginated_list/action_bar/ActionBar.module.scss index 0e8c3801..e3349950 100644 --- a/src/components/list/paginated_list/action_bar/ActionBar.module.scss +++ b/src/components/list/paginated_list/action_bar/ActionBar.module.scss @@ -60,17 +60,82 @@ } } +.tagSection { + position: relative; + display: flex; + align-items: stretch; + width: 100%; + max-width: 100%; +} + .tagList { display: flex; flex-direction: row; justify-content: flex-start; + flex: 1; overflow-x: auto; overflow-y: hidden; gap: spacing.$spacer-md; padding-bottom: spacing.$spacer-md; + scrollbar-width: none; @include display.media-breakpoint-down(xs) { gap: spacing.$spacer-sm; } + + &::-webkit-scrollbar { + display: none; + } +} + +.arrow { + position: absolute; + top: 0; + bottom: 0; + z-index: 2; + display: flex; + align-items: center; + justify-content: center; + border: none; + cursor: pointer; + padding: 0; + transition: opacity 200ms ease; + outline: none; + background: none; + line-height: 0; + + svg { + display: block; + } + + &:focus-visible { + outline: 2px solid theme.$call-primary; + outline-offset: -2px; + } +} + +.arrowLeft { + left: 0; + padding-left: spacing.$spacer-xs; + background: linear-gradient(to right, theme.$background-color-container 40%, transparent); + + svg { + transform: rotate(90deg); + } +} + +.arrowRight { + right: 0; + padding-right: spacing.$spacer-xs; + background: linear-gradient(to left, theme.$background-color-container 40%, transparent); + + svg { + transform: rotate(-90deg); + } +} + +.arrowHidden { + opacity: 0; + pointer-events: none; } .tagItem {