diff --git a/rsconcept/frontend/src/app/ErrorFallback.tsx b/rsconcept/frontend/src/app/ErrorFallback.tsx index c55f2af0..4447a277 100644 --- a/rsconcept/frontend/src/app/ErrorFallback.tsx +++ b/rsconcept/frontend/src/app/ErrorFallback.tsx @@ -5,7 +5,7 @@ import Button from '../components/ui/Button'; function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) { return ( -
+

Что-то пошло не так!

); diff --git a/rsconcept/frontend/src/pages/ManualsPage/TopicsStatic.tsx b/rsconcept/frontend/src/pages/ManualsPage/TopicsStatic.tsx index c63b93e3..58f94d6c 100644 --- a/rsconcept/frontend/src/pages/ManualsPage/TopicsStatic.tsx +++ b/rsconcept/frontend/src/pages/ManualsPage/TopicsStatic.tsx @@ -1,9 +1,10 @@ import clsx from 'clsx'; +import SelectTree from '@/components/ui/SelectTree'; import { useConceptOptions } from '@/context/OptionsContext'; -import { HelpTopic } from '@/models/miscellaneous'; - -import TopicsTree from './TopicsTree'; +import { HelpTopic, topicParent } from '@/models/miscellaneous'; +import { prefixes } from '@/utils/constants'; +import { describeHelpTopic, labelHelpTopic } from '@/utils/labels'; interface TopicsStaticProps { activeTopic: HelpTopic; @@ -13,7 +14,14 @@ interface TopicsStaticProps { function TopicsStatic({ activeTopic, onChangeTopic }: TopicsStaticProps) { const { calculateHeight } = useConceptOptions(); return ( -
item as HelpTopic)} + value={activeTopic} + setValue={onChangeTopic} + prefix={prefixes.topic_list} + getParent={item => topicParent.get(item) ?? item} + getLabel={labelHelpTopic} + getDescription={describeHelpTopic} className={clsx( 'sticky top-0 left-0', 'w-[14.5rem] cc-scroll-y', @@ -24,9 +32,7 @@ function TopicsStatic({ activeTopic, onChangeTopic }: TopicsStaticProps) { 'select-none' )} style={{ maxHeight: calculateHeight('2.25rem + 2px') }} - > - -
+ /> ); } diff --git a/rsconcept/frontend/src/pages/ManualsPage/TopicsTree.tsx b/rsconcept/frontend/src/pages/ManualsPage/TopicsTree.tsx deleted file mode 100644 index 2898c4d3..00000000 --- a/rsconcept/frontend/src/pages/ManualsPage/TopicsTree.tsx +++ /dev/null @@ -1,127 +0,0 @@ -'use client'; - -import clsx from 'clsx'; -import { AnimatePresence, motion } from 'framer-motion'; -import { useCallback, useLayoutEffect, useState } from 'react'; - -import { IconDropArrow, IconPageRight } from '@/components/Icons'; -import { CProps } from '@/components/props'; -import MiniButton from '@/components/ui/MiniButton'; -import Overlay from '@/components/ui/Overlay'; -import { foldableTopics, HelpTopic, topicParent } from '@/models/miscellaneous'; -import { animateSideAppear } from '@/styling/animations'; -import { globals, prefixes } from '@/utils/constants'; -import { describeHelpTopic, labelHelpTopic } from '@/utils/labels'; - -interface TopicsTreeProps { - activeTopic: HelpTopic; - onChangeTopic: (newTopic: HelpTopic) => void; -} - -function TopicsTree({ activeTopic, onChangeTopic }: TopicsTreeProps) { - const [topicFolded, setFolded] = useState>( - new Map( - Object.values(HelpTopic).map(value => { - const topic = value as HelpTopic; - return [topic, true]; - }) - ) - ); - - useLayoutEffect(() => { - setFolded( - new Map( - Object.values(HelpTopic).map(value => { - const topic = value as HelpTopic; - return [ - topic, - topicParent.get(activeTopic) !== topic && topicParent.get(topicParent.get(activeTopic)!) !== topic - ]; - }) - ) - ); - }, [activeTopic]); - - const onFoldTopic = useCallback( - (target: HelpTopic, showChildren: boolean) => { - if (topicFolded.get(target) === !showChildren) { - return; - } - setFolded( - new Map( - Object.values(HelpTopic).map(value => { - const topic = value as HelpTopic; - if (topic === target) { - return [topic, !showChildren]; - } - if ( - !showChildren && - (topicParent.get(topic) === target || topicParent.get(topicParent.get(topic)!) === target) - ) { - return [topic, true]; - } - const oldValue = topicFolded.get(topic)!; - return [topic, oldValue]; - }) - ) - ); - }, - [topicFolded] - ); - - const handleClickFold = useCallback( - (event: CProps.EventMouse, topic: HelpTopic, showChildren: boolean) => { - event.preventDefault(); - event.stopPropagation(); - onFoldTopic(topic, showChildren); - }, - [onFoldTopic] - ); - - return ( - - {Object.values(HelpTopic).map((topic, index) => { - const parent = topicParent.get(topic); - if (parent !== topic && topicFolded.get(topicParent.get(topic)!)) { - return null; - } - const isFoldable = !!foldableTopics.find(id => id === topic); - const isFolded = topicFolded.get(topic)!; - return ( - onChangeTopic(topic)} - initial={{ ...animateSideAppear.initial }} - animate={{ ...animateSideAppear.animate }} - exit={{ ...animateSideAppear.exit }} - > - {isFoldable ? ( - - : } - onClick={event => handleClickFold(event, topic, isFolded)} - /> - - ) : null} - {topicParent.get(topic) === topic ? labelHelpTopic(topic) : `- ${labelHelpTopic(topic).toLowerCase()}`} - - ); - })} - - ); -} - -export default TopicsTree; diff --git a/rsconcept/frontend/src/styling/animations.ts b/rsconcept/frontend/src/styling/animations.ts index 61dce04c..e6b141e6 100644 --- a/rsconcept/frontend/src/styling/animations.ts +++ b/rsconcept/frontend/src/styling/animations.ts @@ -210,22 +210,32 @@ export const animateSideView = { export const animateSideAppear = { initial: { - clipPath: 'inset(0% 100% 0% 0%)' + height: 0, + opacity: 0 }, animate: { - clipPath: 'inset(0% 0% 0% 0%)', + height: 'auto', + opacity: 1, transition: { - type: 'spring', - bounce: 0, - duration: 0.3 + height: { + duration: 0.25 + }, + opacity: { + delay: 0.25, + duration: 0 + } } }, exit: { - clipPath: 'inset(0% 100% 0% 0%)', + height: 0, + opacity: 0, transition: { - type: 'spring', - bounce: 0, - duration: 0.3 + height: { + duration: 0.25 + }, + opacity: { + duration: 0 + } } } };