mirror of
https://github.com/NovaOSS/nova-betterchat.git
synced 2024-11-25 17:43:58 +01:00
feat: folder colors (#191)
This commit is contained in:
parent
892e7792ba
commit
4823b1dc38
17
src/assets/icons/ColorPaletteIcon.tsx
Normal file
17
src/assets/icons/ColorPaletteIcon.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
|
||||
const ColorPaletteIcon = (props: React.SVGProps<SVGSVGElement>) => {
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 24 24'
|
||||
fill='currentColor'
|
||||
height='1em'
|
||||
width='1em'
|
||||
{...props}
|
||||
>
|
||||
<path d='M12 22A10 10 0 012 12 10 10 0 0112 2c5.5 0 10 4 10 9a6 6 0 01-6 6h-1.8c-.3 0-.5.2-.5.5 0 .1.1.2.1.3.4.5.6 1.1.6 1.7.1 1.4-1 2.5-2.4 2.5m0-18a8 8 0 00-8 8 8 8 0 008 8c.3 0 .5-.2.5-.5 0-.2-.1-.3-.1-.4-.4-.5-.6-1-.6-1.6 0-1.4 1.1-2.5 2.5-2.5H16a4 4 0 004-4c0-3.9-3.6-7-8-7m-5.5 6c.8 0 1.5.7 1.5 1.5S7.3 13 6.5 13 5 12.3 5 11.5 5.7 10 6.5 10m3-4c.8 0 1.5.7 1.5 1.5S10.3 9 9.5 9 8 8.3 8 7.5 8.7 6 9.5 6m5 0c.8 0 1.5.7 1.5 1.5S15.3 9 14.5 9 13 8.3 13 7.5 13.7 6 14.5 6m3 4c.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5-1.5-.7-1.5-1.5.7-1.5 1.5-1.5z' />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColorPaletteIcon;
|
|
@ -14,6 +14,10 @@ import EditIcon from '@icon/EditIcon';
|
|||
import DeleteIcon from '@icon/DeleteIcon';
|
||||
import CrossIcon from '@icon/CrossIcon';
|
||||
import TickIcon from '@icon/TickIcon';
|
||||
import ColorPaletteIcon from '@icon/ColorPaletteIcon';
|
||||
import RefreshIcon from '@icon/RefreshIcon';
|
||||
|
||||
import { folderColorOptions } from '@constants/color';
|
||||
|
||||
const ChatFolder = ({
|
||||
folderChats,
|
||||
|
@ -24,16 +28,19 @@ const ChatFolder = ({
|
|||
}) => {
|
||||
const folderName = useStore((state) => state.folders[folderId].name);
|
||||
const isExpanded = useStore((state) => state.folders[folderId].expanded);
|
||||
const color = useStore((state) => state.folders[folderId].color);
|
||||
|
||||
const setChats = useStore((state) => state.setChats);
|
||||
const setFolders = useStore((state) => state.setFolders);
|
||||
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const folderRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [_folderName, _setFolderName] = useState<string>(folderName);
|
||||
const [isEdit, setIsEdit] = useState<boolean>(false);
|
||||
const [isDelete, setIsDelete] = useState<boolean>(false);
|
||||
const [isHover, setIsHover] = useState<boolean>(false);
|
||||
const [showPalette, setShowPalette] = useState<boolean>(false);
|
||||
|
||||
const editTitle = () => {
|
||||
const updatedFolders: FolderCollection = JSON.parse(
|
||||
|
@ -62,6 +69,16 @@ const ChatFolder = ({
|
|||
setIsDelete(false);
|
||||
};
|
||||
|
||||
const updateColor = (_color?: string) => {
|
||||
const updatedFolders: FolderCollection = JSON.parse(
|
||||
JSON.stringify(useStore.getState().folders)
|
||||
);
|
||||
if (_color) updatedFolders[folderId].color = _color;
|
||||
else delete updatedFolders[folderId].color;
|
||||
setFolders(updatedFolders);
|
||||
setShowPalette(false);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
|
@ -133,8 +150,20 @@ const ChatFolder = ({
|
|||
onDragLeave={handleDragLeave}
|
||||
>
|
||||
<div
|
||||
className='flex py-3 px-3 items-center gap-3 relative rounded-md hover:bg-gray-850 break-all cursor-pointer'
|
||||
style={{ background: color || '' }}
|
||||
className={`${
|
||||
color ? '' : 'hover:bg-gray-850'
|
||||
} transition-colors flex py-3 px-3 items-center gap-3 relative rounded-md break-all cursor-pointer`}
|
||||
onClick={toggleExpanded}
|
||||
ref={folderRef}
|
||||
onMouseEnter={() => {
|
||||
if (color && folderRef.current)
|
||||
folderRef.current.style.background = `${color}dd`;
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
if (color && folderRef.current)
|
||||
folderRef.current.style.background = color;
|
||||
}}
|
||||
>
|
||||
<FolderIcon className='h-4 w-4' />
|
||||
<div className='flex-1 text-ellipsis max-h-5 overflow-hidden break-all relative'>
|
||||
|
@ -169,6 +198,40 @@ const ChatFolder = ({
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className='relative'>
|
||||
<button
|
||||
className='p-1 hover:text-white'
|
||||
onClick={() => {
|
||||
setShowPalette((prev) => !prev);
|
||||
}}
|
||||
>
|
||||
<ColorPaletteIcon />
|
||||
</button>
|
||||
{showPalette && (
|
||||
<div className='absolute left-0 bottom-0 translate-y-full p-2 z-20 bg-gray-900 rounded border border-gray-600 flex flex-col gap-2 items-center'>
|
||||
<>
|
||||
{folderColorOptions.map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
style={{ background: c }}
|
||||
className={`hover:scale-90 transition-transform h-4 w-4 rounded-full`}
|
||||
onClick={() => {
|
||||
updateColor(c);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<button
|
||||
onClick={() => {
|
||||
updateColor();
|
||||
}}
|
||||
>
|
||||
<RefreshIcon />
|
||||
</button>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<button
|
||||
className='p-1 hover:text-white'
|
||||
onClick={() => setIsEdit(true)}
|
||||
|
|
7
src/constants/color.ts
Normal file
7
src/constants/color.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const folderColorOptions = [
|
||||
'#be123c', // rose-700
|
||||
'#6d28d9', // violet-700
|
||||
'#0369a1', // sky-700
|
||||
'#047857', // emerald-700
|
||||
'#b45309', // amber-700
|
||||
];
|
Loading…
Reference in a new issue