chore: adjust list details ui (#128)

* chore: detail

* chore: list detail ui

* chore: adjust list details ui
This commit is contained in:
BiggerRain
2025-02-08 15:26:02 +08:00
committed by GitHub
parent cb4d9e7184
commit 17b3b97bec
6 changed files with 58 additions and 78 deletions

View File

@@ -37,7 +37,7 @@ const ChatSwitch: React.FC<ChatSwitchProps> = ({ isChatMode, onChange }) => {
role="switch" role="switch"
aria-checked={isChatMode} aria-checked={isChatMode}
className={`relative flex items-center justify-between w-10 h-[18px] rounded-full cursor-pointer transition-colors duration-300 ${ className={`relative flex items-center justify-between w-10 h-[18px] rounded-full cursor-pointer transition-colors duration-300 ${
isChatMode ? "bg-[#0072ff]" : "bg-[#950599]" isChatMode ? "bg-[#0072ff]" : "bg-[var(--coco-primary-color)]"
}`} }`}
onClick={handleToggle} onClick={handleToggle}
> >

View File

@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import {formatter} from "@/utils/index" import { formatter } from "@/utils/index";
import TypeIcon from "@/components/Common/Icons/TypeIcon"; import TypeIcon from "@/components/Common/Icons/TypeIcon";
interface DocumentDetailProps { interface DocumentDetailProps {

View File

@@ -15,6 +15,8 @@ interface DocumentListProps {
input: string; input: string;
isChatMode: boolean; isChatMode: boolean;
selectedId?: string; selectedId?: string;
viewMode: "detail" | "list";
setViewMode: (mode: "detail" | "list") => void;
} }
const PAGE_SIZE = 20; const PAGE_SIZE = 20;
@@ -23,6 +25,8 @@ export const DocumentList: React.FC<DocumentListProps> = ({
input, input,
getDocDetail, getDocDetail,
isChatMode, isChatMode,
viewMode,
setViewMode,
}) => { }) => {
const sourceData = useSearchStore((state) => state.sourceData); const sourceData = useSearchStore((state) => state.sourceData);
@@ -196,9 +200,17 @@ export const DocumentList: React.FC<DocumentListProps> = ({
}, [selectedItem]); }, [selectedItem]);
return ( return (
<div className="w-[50%] border-r border-gray-200 dark:border-gray-700 flex flex-col h-full"> <div
className={`border-r border-gray-200 dark:border-gray-700 flex flex-col h-full ${
viewMode === "list" ? "w-[100%]" : "w-[50%]"
}`}
>
<div className="px-2 flex-shrink-0"> <div className="px-2 flex-shrink-0">
<SearchHeader total={total} /> <SearchHeader
total={total}
viewMode={viewMode}
setViewMode={setViewMode}
/>
</div> </div>
<div <div
@@ -220,7 +232,7 @@ export const DocumentList: React.FC<DocumentListProps> = ({
}} }}
className={`w-full px-2 py-2.5 text-sm flex items-center gap-3 rounded-lg transition-colors cursor-pointer ${ className={`w-full px-2 py-2.5 text-sm flex items-center gap-3 rounded-lg transition-colors cursor-pointer ${
isSelected isSelected
? "text-white bg-[#950599] hover:bg-[#950599]" ? "text-white bg-[var(--coco-primary-color)] hover:bg-[var(--coco-primary-color)]"
: "text-[#333] dark:text-[#d8d8d8]" : "text-[#333] dark:text-[#d8d8d8]"
}`} }`}
> >

View File

@@ -219,7 +219,7 @@ function DropdownList({
} }
}} }}
className={`w-full px-2 py-2.5 text-sm flex gap-7 items-center justify-between rounded-lg transition-colors cursor-pointer ${isSelected className={`w-full px-2 py-2.5 text-sm flex gap-7 items-center justify-between rounded-lg transition-colors cursor-pointer ${isSelected
? "text-white bg-[#950599] hover:bg-[#950599]" ? "text-white bg-[var(--coco-primary-color)] hover:bg-[var(--coco-primary-color)]"
: "text-[#333] dark:text-[#d8d8d8]" : "text-[#333] dark:text-[#d8d8d8]"
}`} }`}
> >

View File

@@ -1,70 +1,17 @@
import React, { useState } from "react"; import React from "react";
import { Menu, MenuButton, MenuItems, MenuItem } from "@headlessui/react"; import { AlignLeft, Columns2 } from "lucide-react";
import { ChevronDown } from "lucide-react";
interface FilterOption {
id: string;
label: string;
}
interface FilterDropdownProps {
label: string;
options: FilterOption[];
value?: string;
onChange: (value: string) => void;
}
const FilterDropdown: React.FC<FilterDropdownProps> = ({
label,
options,
value,
onChange,
}) => {
return (
<Menu as="div" className="relative">
<MenuButton className="inline-flex items-center px-2.5 py-1 text-xs bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-lg border border-gray-200 dark:border-gray-700 font-medium">
{label}
<ChevronDown className="w-3.5 h-3.5 ml-1 text-gray-500 dark:text-gray-400" />
</MenuButton>
<MenuItems className="absolute right-0 mt-1 w-44 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 py-1 z-10 focus:outline-none">
{options.map((option) => (
<MenuItem key={option.id}>
{({ active }) => (
<button
onClick={() => onChange(option.id)}
className={`w-full text-left px-3 py-1.5 text-xs ${
active ? "bg-gray-50 dark:bg-gray-700" : ""
} ${
value === option.id
? "text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/50"
: "text-gray-700 dark:text-gray-300"
}`}
>
{option.label}
</button>
)}
</MenuItem>
))}
</MenuItems>
</Menu>
);
};
const typeOptions: FilterOption[] = [
{ id: "all", label: "All" },
{ id: "doc", label: "Doc" },
{ id: "image", label: "Image" },
{ id: "code", label: "Code" },
];
interface SearchHeaderProps { interface SearchHeaderProps {
total: number; total: number;
viewMode: "detail" | "list";
setViewMode: (mode: "detail" | "list") => void;
} }
export const SearchHeader: React.FC<SearchHeaderProps> = ({ total }) => { export const SearchHeader: React.FC<SearchHeaderProps> = ({
const [typeFilter, setTypeFilter] = useState("all"); total,
viewMode,
setViewMode,
}) => {
return ( return (
<div className="flex items-center justify-between py-1"> <div className="flex items-center justify-between py-1">
<div className="text-xs text-gray-600 dark:text-gray-400"> <div className="text-xs text-gray-600 dark:text-gray-400">
@@ -75,12 +22,28 @@ export const SearchHeader: React.FC<SearchHeaderProps> = ({ total }) => {
results results
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
<FilterDropdown <div className="flex bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5">
label="Type" <button
options={typeOptions} onClick={() => setViewMode("list")}
value={typeFilter} className={`p-1 rounded ${
onChange={setTypeFilter} viewMode === "list"
/> ? "bg-white dark:bg-gray-700 shadow-sm text-[var(--coco-primary-color)]"
: "text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
}`}
>
<AlignLeft className="w-4 h-4" />
</button>
<button
onClick={() => setViewMode("detail")}
className={`p-1 rounded ${
viewMode === "detail"
? "bg-white dark:bg-gray-700 shadow-sm text-[var(--coco-primary-color)]"
: "text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
}`}
>
<Columns2 className="w-4 h-4" />
</button>
</div>
</div> </div>
</div> </div>
); );

View File

@@ -12,9 +12,10 @@ export function SearchResults({ input, isChatMode }: SearchResultsProps) {
const [selectedDocumentId, setSelectedDocumentId] = useState("1"); const [selectedDocumentId, setSelectedDocumentId] = useState("1");
const [detailData, setDetailData] = useState<any>({}); const [detailData, setDetailData] = useState<any>({});
const [viewMode, setViewMode] = useState<"detail" | "list">("detail");
function getDocDetail(detail: any) { function getDocDetail(detail: any) {
setDetailData(detail) setDetailData(detail);
} }
return ( return (
@@ -27,12 +28,16 @@ export function SearchResults({ input, isChatMode }: SearchResultsProps) {
input={input} input={input}
getDocDetail={getDocDetail} getDocDetail={getDocDetail}
isChatMode={isChatMode} isChatMode={isChatMode}
viewMode={viewMode}
setViewMode={setViewMode}
/> />
{/* Right Panel */} {/* Right Panel */}
<div className="flex-1 overflow-y-auto custom-scrollbar"> {viewMode === "detail" && (
<DocumentDetail document={detailData} /> <div className="flex-1 overflow-y-auto custom-scrollbar">
</div> <DocumentDetail document={detailData} />
</div>
)}
</div> </div>
</div> </div>
); );