Update layout and add tooltips (#483)
This commit is contained in:
parent
5190b109c9
commit
affd387d03
4 changed files with 107 additions and 48 deletions
|
|
@ -142,5 +142,5 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.suggestion-highlight {
|
.suggestion-highlight {
|
||||||
@apply bg-yellow-100 hover:bg-yellow-200 dark:hover:bg-yellow-400/50 dark:text-yellow-50 dark:bg-yellow-400/40;
|
@apply bg-blue-100 hover:bg-blue-200 dark:hover:bg-blue-400/50 dark:text-blue-50 dark:bg-blue-400/40;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,13 @@ import {
|
||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
import useSWR, { useSWRConfig } from 'swr';
|
import useSWR, { useSWRConfig } from 'swr';
|
||||||
import { useDebounceCallback, useWindowSize } from 'usehooks-ts';
|
import {
|
||||||
|
useCopyToClipboard,
|
||||||
|
useDebounceCallback,
|
||||||
|
useWindowSize,
|
||||||
|
} from 'usehooks-ts';
|
||||||
|
|
||||||
import { Document, Suggestion } from '@/db/schema';
|
import { Document, Suggestion } from '@/db/schema';
|
||||||
import { fetcher } from '@/lib/utils';
|
import { fetcher } from '@/lib/utils';
|
||||||
|
|
@ -18,13 +23,14 @@ import { fetcher } from '@/lib/utils';
|
||||||
import { DiffView } from './diffview';
|
import { DiffView } from './diffview';
|
||||||
import { DocumentSkeleton } from './document-skeleton';
|
import { DocumentSkeleton } from './document-skeleton';
|
||||||
import { Editor } from './editor';
|
import { Editor } from './editor';
|
||||||
import { CrossIcon, DeltaIcon, RedoIcon, UndoIcon } from './icons';
|
import { CopyIcon, CrossIcon, DeltaIcon, RedoIcon, UndoIcon } from './icons';
|
||||||
import { Markdown } from './markdown';
|
import { Markdown } from './markdown';
|
||||||
import { Message as PreviewMessage } from './message';
|
import { Message as PreviewMessage } from './message';
|
||||||
import { MultimodalInput } from './multimodal-input';
|
import { MultimodalInput } from './multimodal-input';
|
||||||
import { Toolbar } from './toolbar';
|
import { Toolbar } from './toolbar';
|
||||||
import { useScrollToBottom } from './use-scroll-to-bottom';
|
import { useScrollToBottom } from './use-scroll-to-bottom';
|
||||||
import { VersionFooter } from './version-footer';
|
import { VersionFooter } from './version-footer';
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
||||||
export interface UICanvas {
|
export interface UICanvas {
|
||||||
title: string;
|
title: string;
|
||||||
documentId: string;
|
documentId: string;
|
||||||
|
|
@ -233,6 +239,8 @@ export function Canvas({
|
||||||
const { width: windowWidth, height: windowHeight } = useWindowSize();
|
const { width: windowWidth, height: windowHeight } = useWindowSize();
|
||||||
const isMobile = windowWidth ? windowWidth < 768 : false;
|
const isMobile = windowWidth ? windowWidth < 768 : false;
|
||||||
|
|
||||||
|
const [_, copyToClipboard] = useCopyToClipboard();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="flex flex-row h-dvh w-dvw fixed top-0 left-0 z-50 bg-muted"
|
className="flex flex-row h-dvh w-dvw fixed top-0 left-0 z-50 bg-muted"
|
||||||
|
|
@ -243,10 +251,10 @@ export function Canvas({
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative w-[400px] bg-muted dark:bg-background h-dvh shrink-0"
|
className="relative w-[400px] bg-muted dark:bg-background h-dvh shrink-0"
|
||||||
initial={{ opacity: 0, x: 10, scale: 1 }}
|
initial={{ opacity: 0, x: windowWidth - 420, scale: 1 }}
|
||||||
animate={{
|
animate={{
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
x: 0,
|
x: windowWidth - 400,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
transition: {
|
transition: {
|
||||||
delay: 0.2,
|
delay: 0.2,
|
||||||
|
|
@ -255,7 +263,12 @@ export function Canvas({
|
||||||
damping: 30,
|
damping: 30,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
exit={{ opacity: 0, x: 10, scale: 0.95, transition: { delay: 0 } }}
|
exit={{
|
||||||
|
opacity: 0,
|
||||||
|
x: windowWidth - 420,
|
||||||
|
scale: 0.95,
|
||||||
|
transition: { delay: 0 },
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{!isCurrentVersion && (
|
{!isCurrentVersion && (
|
||||||
|
|
@ -349,7 +362,7 @@ export function Canvas({
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
x: 400,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
height: windowHeight,
|
height: windowHeight,
|
||||||
width: windowWidth ? windowWidth - 400 : 'calc(100dvw-400px)',
|
width: windowWidth ? windowWidth - 400 : 'calc(100dvw-400px)',
|
||||||
|
|
@ -411,33 +424,62 @@ export function Canvas({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row gap-1">
|
<div className="flex flex-row gap-1">
|
||||||
<div
|
<Tooltip>
|
||||||
className="cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700"
|
<TooltipTrigger>
|
||||||
onClick={() => {
|
<div
|
||||||
handleVersionChange('prev');
|
className="cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700"
|
||||||
}}
|
onClick={() => {
|
||||||
>
|
copyToClipboard(canvas.content);
|
||||||
<UndoIcon size={18} />
|
toast.success('Copied to clipboard!');
|
||||||
</div>
|
}}
|
||||||
<div
|
>
|
||||||
className="cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700"
|
<CopyIcon size={18} />
|
||||||
onClick={() => {
|
</div>
|
||||||
handleVersionChange('next');
|
</TooltipTrigger>
|
||||||
}}
|
<TooltipContent>Copy to clipboard</TooltipContent>
|
||||||
>
|
</Tooltip>
|
||||||
<RedoIcon size={18} />
|
<Tooltip>
|
||||||
</div>
|
<TooltipTrigger>
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className="cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700"
|
||||||
'cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700',
|
onClick={() => {
|
||||||
{ 'bg-muted dark:bg-zinc-700': mode === 'diff' }
|
handleVersionChange('prev');
|
||||||
)}
|
}}
|
||||||
onClick={() => {
|
>
|
||||||
handleVersionChange('toggle');
|
<UndoIcon size={18} />
|
||||||
}}
|
</div>
|
||||||
>
|
</TooltipTrigger>
|
||||||
<DeltaIcon size={18} />
|
<TooltipContent>View Previous version</TooltipContent>
|
||||||
</div>
|
</Tooltip>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<div
|
||||||
|
className="cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700"
|
||||||
|
onClick={() => {
|
||||||
|
handleVersionChange('next');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RedoIcon size={18} />
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>View Next version</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
'cursor-pointer hover:bg-muted p-2 rounded-lg text-muted-foreground dark:hover:bg-zinc-700',
|
||||||
|
{ 'bg-muted dark:bg-zinc-700': mode === 'diff' }
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
handleVersionChange('toggle');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DeltaIcon size={18} />
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>View changes</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -468,6 +510,19 @@ export function Canvas({
|
||||||
{suggestions ? (
|
{suggestions ? (
|
||||||
<div className="md:hidden h-dvh w-12 shrink-0" />
|
<div className="md:hidden h-dvh w-12 shrink-0" />
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
<AnimatePresence>
|
||||||
|
{isCurrentVersion && (
|
||||||
|
<Toolbar
|
||||||
|
isToolbarVisible={isToolbarVisible}
|
||||||
|
setIsToolbarVisible={setIsToolbarVisible}
|
||||||
|
append={append}
|
||||||
|
isLoading={isLoading}
|
||||||
|
stop={stop}
|
||||||
|
setMessages={setMessages}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -482,19 +537,6 @@ export function Canvas({
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
<AnimatePresence>
|
|
||||||
{isCurrentVersion && (
|
|
||||||
<Toolbar
|
|
||||||
isToolbarVisible={isToolbarVisible}
|
|
||||||
setIsToolbarVisible={setIsToolbarVisible}
|
|
||||||
append={append}
|
|
||||||
isLoading={isLoading}
|
|
||||||
stop={stop}
|
|
||||||
setMessages={setMessages}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,3 +745,20 @@ export const PlusIcon = ({ size = 16 }: { size?: number }) => (
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const CopyIcon = ({ size = 16 }: { size?: number }) => (
|
||||||
|
<svg
|
||||||
|
height={size}
|
||||||
|
strokeLinejoin="round"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
width={size}
|
||||||
|
style={{ color: 'currentcolor' }}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M2.75 0.5C1.7835 0.5 1 1.2835 1 2.25V9.75C1 10.7165 1.7835 11.5 2.75 11.5H3.75H4.5V10H3.75H2.75C2.61193 10 2.5 9.88807 2.5 9.75V2.25C2.5 2.11193 2.61193 2 2.75 2H8.25C8.38807 2 8.5 2.11193 8.5 2.25V3H10V2.25C10 1.2835 9.2165 0.5 8.25 0.5H2.75ZM7.75 4.5C6.7835 4.5 6 5.2835 6 6.25V13.75C6 14.7165 6.7835 15.5 7.75 15.5H13.25C14.2165 15.5 15 14.7165 15 13.75V6.25C15 5.2835 14.2165 4.5 13.25 4.5H7.75ZM7.5 6.25C7.5 6.11193 7.61193 6 7.75 6H13.25C13.3881 6 13.5 6.11193 13.5 6.25V13.75C13.5 13.8881 13.3881 14 13.25 14H7.75C7.61193 14 7.5 13.8881 7.5 13.75V6.25Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,7 @@ export const Toolbar = ({
|
||||||
return (
|
return (
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider delayDuration={0}>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="cursor-pointer fixed right-6 bottom-6 p-1.5 border rounded-full shadow-lg bg-background flex flex-col justify-end"
|
className="cursor-pointer absolute right-6 bottom-6 p-1.5 border rounded-full shadow-lg bg-background flex flex-col justify-end"
|
||||||
initial={{ opacity: 0, y: -20, scale: 1 }}
|
initial={{ opacity: 0, y: -20, scale: 1 }}
|
||||||
animate={
|
animate={
|
||||||
isToolbarVisible
|
isToolbarVisible
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue