From a4dd1e2f6e92f90c201287ea6a83a865a7f10d71 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Fri, 3 Jan 2025 13:26:30 +0200 Subject: [PATCH] feat(MultiSelectMenu): scroll into view --- .../MultiselectMenu/Dropdown/Dropdown.tsx | 70 +++++++++++++------ .../Dropdown/Option/Option.tsx | 10 +-- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/common/MultiselectMenu/Dropdown/Dropdown.tsx b/src/common/MultiselectMenu/Dropdown/Dropdown.tsx index cb7de76c2..eea0d679e 100644 --- a/src/common/MultiselectMenu/Dropdown/Dropdown.tsx +++ b/src/common/MultiselectMenu/Dropdown/Dropdown.tsx @@ -1,6 +1,6 @@ // Copyright (C) 2017-2024 Smart code 203358507 -import React from 'react'; +import React, { useRef, useEffect, useCallback } from 'react'; import Button from 'stremio/common/Button'; import { useTranslation } from 'react-i18next'; import classNames from 'classnames'; @@ -19,33 +19,57 @@ type Props = { const Dropdown = ({ level, setLevel, options, onSelect, selectedOption, menuOpen }: Props) => { const { t } = useTranslation(); + const optionsRef = useRef(new Map()); + const containerRef = useRef(null); - const onBackButtonClick = () => { + const handleSetOptionRef = useCallback((value: number) => (node: HTMLButtonElement | null) => { + if (node) { + optionsRef.current.set(value, node); + } else { + optionsRef.current.delete(value); + } + }, []); + + const handleBackClick = useCallback(() => { setLevel(level - 1); - }; + }, [setLevel, level]); + + useEffect(() => { + if (menuOpen && selectedOption && containerRef.current) { + const selectedNode = optionsRef.current.get(selectedOption.value); + if (selectedNode) { + selectedNode.scrollIntoView({ + behavior: 'smooth', + block: 'nearest' + }); + } + } + }, [menuOpen, selectedOption]); return ( -
- { - level > 0 ? - - : null +
+ {level > 0 ? + + : null } - { - options - .filter((option: MultiselectMenuOption) => !option.hidden) - .map((option: MultiselectMenuOption, index) => ( -
); diff --git a/src/common/MultiselectMenu/Dropdown/Option/Option.tsx b/src/common/MultiselectMenu/Dropdown/Option/Option.tsx index 13ea37bd5..3812282a2 100644 --- a/src/common/MultiselectMenu/Dropdown/Option/Option.tsx +++ b/src/common/MultiselectMenu/Dropdown/Option/Option.tsx @@ -1,6 +1,6 @@ // Copyright (C) 2017-2024 Smart code 203358507 -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo, forwardRef } from 'react'; import classNames from 'classnames'; import Button from 'stremio/common/Button'; import styles from './Option.less'; @@ -12,7 +12,7 @@ type Props = { onSelect: (value: number) => void; }; -const Option = ({ option, selectedOption, onSelect }: Props) => { +const Option = forwardRef(({ option, selectedOption, onSelect }, ref) => { // consider using option.id === selectedOption?.id instead const selected = useMemo(() => option?.value === selectedOption?.value, [option, selectedOption]); @@ -22,6 +22,7 @@ const Option = ({ option, selectedOption, onSelect }: Props) => { return ( ); -}; +}); + +Option.displayName = 'Option'; export default Option;