update: pinned panel 添加展开和收缩动画
This commit is contained in:
parent
ae132cb274
commit
a5b8e9cd87
@ -1,13 +1,13 @@
|
||||
import {Input} from "antd";
|
||||
import {useBoolean, useLocalStorageState, useSetState} from "ahooks";
|
||||
import {useMemo, useState} from "react";
|
||||
import {useBoolean, useLocalStorageState, useSetState,useClickAway} from "ahooks";
|
||||
import {useCallback, useMemo, useRef, useState} from "react";
|
||||
import {clsx} from "clsx";
|
||||
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 styles from './style.module.scss'
|
||||
import {clsx} from "clsx";
|
||||
import {IconPin} from "@/components/icons";
|
||||
|
||||
type SearchPanelProps = {
|
||||
@ -23,7 +23,7 @@ const DEFAULT_STATE = {
|
||||
}
|
||||
export default function SearchPanel({onSearch}: SearchPanelProps) {
|
||||
const tags = useArticleTags();
|
||||
const [panelVisible, {setTrue, setFalse}] = useBoolean(false)
|
||||
const [panelVisible, {set}] = useBoolean(false)
|
||||
const [params, setParams] = useSetState<ApiArticleSearchParams>({
|
||||
pagination,
|
||||
time_flag:1
|
||||
@ -89,6 +89,29 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
|
||||
}
|
||||
return [] as OptionItem[];
|
||||
}, [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`}>
|
||||
<div className="flex justify-between items-center">
|
||||
@ -109,18 +132,17 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="filter-container mt-5 h-[40px]">
|
||||
<div className="filter-container mt-5">
|
||||
<div className="list-container relative">
|
||||
<div className="justify-between flex items-center border-b pb-2 overflow-hidden">
|
||||
<div
|
||||
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' : ''}`}
|
||||
onClick={() => {
|
||||
handleFilter({tag_level_1_id: -1, tag_level_2_id: -1})
|
||||
setSubOptions([])
|
||||
}}>全部
|
||||
</div>
|
||||
|
||||
<div className="pinned-tag-list flex flex-wrap overflow-hidden flex-1 min-w-0 h-[32px]">
|
||||
<div className="justify-between flex items-start border-b pb-2 overflow-hidden">
|
||||
<div className="pinned-tag-list flex flex-wrap flex-1 min-w-0">
|
||||
<div
|
||||
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' : ''}`}
|
||||
onClick={() => {
|
||||
handleFilter({tag_level_1_id: -1, tag_level_2_id: -1})
|
||||
setSubOptions([])
|
||||
}}>全部
|
||||
</div>
|
||||
{pinnedList.filter(s => (Number(s.value) !== 999999)).map(it => (
|
||||
<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' : ''}`}
|
||||
@ -131,18 +153,25 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
|
||||
}}>{it.label}</span>)
|
||||
)}
|
||||
</div>
|
||||
<div className="pinned-menu ">
|
||||
<span className={'cursor-pointer block hover:text-blue-500'} onClick={setTrue}>
|
||||
<div className="pinned-menu mt-2">
|
||||
<span className={'cursor-pointer block hover:text-blue-500'} onClick={e=>{
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setTrue();
|
||||
}}>
|
||||
<MenuOutlined style={{fontSize: 20}}/>
|
||||
</span>
|
||||
</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="title font-bold">新闻来源</div>
|
||||
<span className={'cursor-pointer block hover:text-blue-500'} onClick={setFalse}><CloseOutlined
|
||||
style={{fontSize: 20}}/></span>
|
||||
<div className={'cursor-pointer block hover:text-blue-500'} onClick={setFalse}>
|
||||
<UpOutlined style={{fontSize: 20}}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tags-list-container">
|
||||
{
|
||||
@ -166,6 +195,7 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 二级目录 */}
|
||||
{state.tag_level_1_id != -1 && subOptions.length > 0 &&
|
||||
<div
|
||||
|
@ -14,10 +14,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pinnedManagePanel {
|
||||
@apply absolute bg-white top-0 px-4 pt-2 pb-4 rounded shadow-md z-10;
|
||||
.pinnedManagePanelContainer {
|
||||
@apply absolute bg-white top-0 rounded shadow-md z-10;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
transition: height 0.2s ease-in-out;
|
||||
inset-inline: -20px;
|
||||
}
|
||||
.pinnedManagePanel {
|
||||
@apply px-4 pt-2 pb-4 grid;
|
||||
|
||||
:global {
|
||||
.btn-panel {
|
||||
|
Loading…
x
Reference in New Issue
Block a user