update: pinned panel 添加展开和收缩动画
This commit is contained in:
parent
ae132cb274
commit
a5b8e9cd87
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user