update: pinned panel 添加展开和收缩动画

This commit is contained in:
LittleBoy 2024-12-23 20:38:31 +08:00
parent ae132cb274
commit a5b8e9cd87
2 changed files with 59 additions and 24 deletions

View File

@ -1,13 +1,13 @@
import {Input} from "antd"; import {Input} from "antd";
import {useBoolean, useLocalStorageState, useSetState} from "ahooks"; import {useBoolean, useLocalStorageState, useSetState,useClickAway} from "ahooks";
import {useMemo, useState} from "react"; import {useCallback, useMemo, useRef, useState} from "react";
import {clsx} from "clsx";
import useArticleTags from "@/hooks/useArticleTags.ts"; import useArticleTags from "@/hooks/useArticleTags.ts";
import {CloseOutlined, MenuOutlined, SearchOutlined} from "@ant-design/icons"; import {UpOutlined, MenuOutlined, SearchOutlined} from "@ant-design/icons";
import TimeSelect from "@/components/form/time-select.tsx"; import TimeSelect from "@/components/form/time-select.tsx";
import styles from './style.module.scss' import styles from './style.module.scss'
import {clsx} from "clsx";
import {IconPin} from "@/components/icons"; import {IconPin} from "@/components/icons";
type SearchPanelProps = { type SearchPanelProps = {
@ -23,7 +23,7 @@ const DEFAULT_STATE = {
} }
export default function SearchPanel({onSearch}: SearchPanelProps) { export default function SearchPanel({onSearch}: SearchPanelProps) {
const tags = useArticleTags(); const tags = useArticleTags();
const [panelVisible, {setTrue, setFalse}] = useBoolean(false) const [panelVisible, {set}] = useBoolean(false)
const [params, setParams] = useSetState<ApiArticleSearchParams>({ const [params, setParams] = useSetState<ApiArticleSearchParams>({
pagination, pagination,
time_flag:1 time_flag:1
@ -89,6 +89,29 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
} }
return [] as OptionItem[]; return [] as OptionItem[];
}, [pinnedTag, tags]) }, [pinnedTag, tags])
const pinnedManagePanel = useRef<HTMLDivElement|null>(null)
const togglePinnedManagePanel = useCallback((visible: boolean) => {
if(!pinnedManagePanel.current){
return;
}
const _target = pinnedManagePanel.current!;
if(visible){
_target.style.height = 'auto'
const {height} = _target.getBoundingClientRect()
_target.style.height = '38px'
requestAnimationFrame(()=>{
_target.style.height = `${height}px`
})
}else{
requestAnimationFrame(()=>{
_target.style.height = '0'
})
}
},[pinnedManagePanel])
const setTrue = ()=> togglePinnedManagePanel(true)
const setFalse = ()=>togglePinnedManagePanel(false)
useClickAway(() => setFalse(), pinnedManagePanel)
return (<div className={`${styles.searchPanel} pt-8 pb-2`}> return (<div className={`${styles.searchPanel} pt-8 pb-2`}>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -109,18 +132,17 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
/> />
</div> </div>
</div> </div>
<div className="filter-container mt-5 h-[40px]"> <div className="filter-container mt-5">
<div className="list-container relative"> <div className="list-container relative">
<div className="justify-between flex items-center border-b pb-2 overflow-hidden"> <div className="justify-between flex items-start border-b pb-2 overflow-hidden">
<div <div className="pinned-tag-list flex flex-wrap flex-1 min-w-0">
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_1_id == -1 ? 'selected' : ''}`} <div
onClick={() => { className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_1_id == -1 ? 'selected' : ''}`}
handleFilter({tag_level_1_id: -1, tag_level_2_id: -1}) onClick={() => {
setSubOptions([]) handleFilter({tag_level_1_id: -1, tag_level_2_id: -1})
}}> setSubOptions([])
</div> }}>
</div>
<div className="pinned-tag-list flex flex-wrap overflow-hidden flex-1 min-w-0 h-[32px]">
{pinnedList.filter(s => (Number(s.value) !== 999999)).map(it => ( {pinnedList.filter(s => (Number(s.value) !== 999999)).map(it => (
<span <span
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_1_id == it.value ? 'selected' : ''}`} className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_1_id == it.value ? 'selected' : ''}`}
@ -131,18 +153,25 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
}}>{it.label}</span>) }}>{it.label}</span>)
)} )}
</div> </div>
<div className="pinned-menu "> <div className="pinned-menu mt-2">
<span className={'cursor-pointer block hover:text-blue-500'} onClick={setTrue}> <span className={'cursor-pointer block hover:text-blue-500'} onClick={e=>{
e.stopPropagation();
e.preventDefault();
setTrue();
}}>
<MenuOutlined style={{fontSize: 20}}/> <MenuOutlined style={{fontSize: 20}}/>
</span> </span>
</div> </div>
</div> </div>
<div ref={pinnedManagePanel} className={clsx(styles.pinnedManagePanelContainer)}>
{/* 固定新闻来源 */} {/* 固定新闻来源 */}
<div className={clsx(styles.pinnedManagePanel, panelVisible ? 'block' : 'hidden')}> <div className={clsx(styles.pinnedManagePanel)}>
<div className="header flex justify-between"> <div className="header flex justify-between">
<div className="title font-bold"></div> <div className="title font-bold"></div>
<span className={'cursor-pointer block hover:text-blue-500'} onClick={setFalse}><CloseOutlined <div className={'cursor-pointer block hover:text-blue-500'} onClick={setFalse}>
style={{fontSize: 20}}/></span> <UpOutlined style={{fontSize: 20}}/>
</div>
</div> </div>
<div className="tags-list-container"> <div className="tags-list-container">
{ {
@ -166,6 +195,7 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
} }
</div> </div>
</div> </div>
</div>
{/* 二级目录 */} {/* 二级目录 */}
{state.tag_level_1_id != -1 && subOptions.length > 0 && {state.tag_level_1_id != -1 && subOptions.length > 0 &&
<div <div

View File

@ -14,10 +14,15 @@
} }
} }
} }
.pinnedManagePanelContainer {
.pinnedManagePanel { @apply absolute bg-white top-0 rounded shadow-md z-10;
@apply absolute bg-white top-0 px-4 pt-2 pb-4 rounded shadow-md z-10; height: 0;
overflow: hidden;
transition: height 0.2s ease-in-out;
inset-inline: -20px; inset-inline: -20px;
}
.pinnedManagePanel {
@apply px-4 pt-2 pb-4 grid;
:global { :global {
.btn-panel { .btn-panel {