mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +01:00
chore: adjust list details ui (#128)
* chore: detail * chore: list detail ui * chore: adjust list details ui
This commit is contained in:
@@ -37,7 +37,7 @@ const ChatSwitch: React.FC<ChatSwitchProps> = ({ isChatMode, onChange }) => {
|
||||
role="switch"
|
||||
aria-checked={isChatMode}
|
||||
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}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
import {formatter} from "@/utils/index"
|
||||
import { formatter } from "@/utils/index";
|
||||
import TypeIcon from "@/components/Common/Icons/TypeIcon";
|
||||
|
||||
interface DocumentDetailProps {
|
||||
|
||||
@@ -15,6 +15,8 @@ interface DocumentListProps {
|
||||
input: string;
|
||||
isChatMode: boolean;
|
||||
selectedId?: string;
|
||||
viewMode: "detail" | "list";
|
||||
setViewMode: (mode: "detail" | "list") => void;
|
||||
}
|
||||
|
||||
const PAGE_SIZE = 20;
|
||||
@@ -23,6 +25,8 @@ export const DocumentList: React.FC<DocumentListProps> = ({
|
||||
input,
|
||||
getDocDetail,
|
||||
isChatMode,
|
||||
viewMode,
|
||||
setViewMode,
|
||||
}) => {
|
||||
const sourceData = useSearchStore((state) => state.sourceData);
|
||||
|
||||
@@ -196,9 +200,17 @@ export const DocumentList: React.FC<DocumentListProps> = ({
|
||||
}, [selectedItem]);
|
||||
|
||||
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">
|
||||
<SearchHeader total={total} />
|
||||
<SearchHeader
|
||||
total={total}
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
/>
|
||||
</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 ${
|
||||
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]"
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -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
|
||||
? "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]"
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -1,70 +1,17 @@
|
||||
import React, { useState } from "react";
|
||||
import { Menu, MenuButton, MenuItems, MenuItem } from "@headlessui/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" },
|
||||
];
|
||||
import React from "react";
|
||||
import { AlignLeft, Columns2 } from "lucide-react";
|
||||
|
||||
interface SearchHeaderProps {
|
||||
total: number;
|
||||
viewMode: "detail" | "list";
|
||||
setViewMode: (mode: "detail" | "list") => void;
|
||||
}
|
||||
|
||||
export const SearchHeader: React.FC<SearchHeaderProps> = ({ total }) => {
|
||||
const [typeFilter, setTypeFilter] = useState("all");
|
||||
|
||||
export const SearchHeader: React.FC<SearchHeaderProps> = ({
|
||||
total,
|
||||
viewMode,
|
||||
setViewMode,
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<div className="text-xs text-gray-600 dark:text-gray-400">
|
||||
@@ -75,12 +22,28 @@ export const SearchHeader: React.FC<SearchHeaderProps> = ({ total }) => {
|
||||
results
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<FilterDropdown
|
||||
label="Type"
|
||||
options={typeOptions}
|
||||
value={typeFilter}
|
||||
onChange={setTypeFilter}
|
||||
/>
|
||||
<div className="flex bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5">
|
||||
<button
|
||||
onClick={() => setViewMode("list")}
|
||||
className={`p-1 rounded ${
|
||||
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>
|
||||
);
|
||||
|
||||
@@ -12,9 +12,10 @@ export function SearchResults({ input, isChatMode }: SearchResultsProps) {
|
||||
const [selectedDocumentId, setSelectedDocumentId] = useState("1");
|
||||
|
||||
const [detailData, setDetailData] = useState<any>({});
|
||||
const [viewMode, setViewMode] = useState<"detail" | "list">("detail");
|
||||
|
||||
function getDocDetail(detail: any) {
|
||||
setDetailData(detail)
|
||||
setDetailData(detail);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -27,12 +28,16 @@ export function SearchResults({ input, isChatMode }: SearchResultsProps) {
|
||||
input={input}
|
||||
getDocDetail={getDocDetail}
|
||||
isChatMode={isChatMode}
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
/>
|
||||
|
||||
{/* Right Panel */}
|
||||
<div className="flex-1 overflow-y-auto custom-scrollbar">
|
||||
<DocumentDetail document={detailData} />
|
||||
</div>
|
||||
{viewMode === "detail" && (
|
||||
<div className="flex-1 overflow-y-auto custom-scrollbar">
|
||||
<DocumentDetail document={detailData} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user