ui: changes for context menu plus alignment + padding (#1179)
This commit is contained in:
parent
eae41c635d
commit
2f9ba09606
4 changed files with 65 additions and 36 deletions
|
|
@ -1,10 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from '@/components/ui/hover-card';
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { ComponentProps } from 'react';
|
||||
import type { LanguageModelUsage } from 'ai';
|
||||
|
|
@ -97,11 +97,11 @@ export const ContextIcon = ({ percent }: ContextIconProps) => {
|
|||
return (
|
||||
<svg
|
||||
aria-label={`${formatPercent(percent)} of model context used`}
|
||||
height="20"
|
||||
height="28"
|
||||
role="img"
|
||||
style={{ color: 'currentcolor' }}
|
||||
viewBox={`0 0 ${ICON_VIEWBOX} ${ICON_VIEWBOX}`}
|
||||
width="20"
|
||||
width="28"
|
||||
>
|
||||
<circle
|
||||
cx={ICON_CENTER}
|
||||
|
|
@ -271,8 +271,8 @@ export const Context = ({
|
|||
n === undefined ? '—' : formatTokens(n);
|
||||
|
||||
return (
|
||||
<HoverCard closeDelay={100} openDelay={100}>
|
||||
<HoverCardTrigger asChild>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
className={cn(
|
||||
'inline-flex select-none items-center gap-1 rounded-md px-1.5 py-1 text-sm',
|
||||
|
|
@ -282,17 +282,18 @@ export const Context = ({
|
|||
type="button"
|
||||
{...props}
|
||||
>
|
||||
<span className="font-medium text-muted-foreground">
|
||||
<span className="font-medium text-muted-foreground hidden">
|
||||
{displayPct}
|
||||
</span>
|
||||
<ContextIcon percent={usedPercent} />
|
||||
</button>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent align="end" side="top" className="w-fit p-3">
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" side="top" className="w-fit p-3">
|
||||
<div className="min-w-[240px] space-y-2">
|
||||
<p className="text-start text-sm">
|
||||
{displayPct} • {used} / {total} tokens
|
||||
</p>
|
||||
<div className="flex justify-between items-start text-sm">
|
||||
<span>{displayPct}</span>
|
||||
<span className="text-muted-foreground">{used} / {total} tokens</span>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Progress className="h-2 bg-muted" value={usedPercent} />
|
||||
</div>
|
||||
|
|
@ -339,7 +340,7 @@ export const Context = ({
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -698,6 +698,30 @@ export const DeltaIcon = ({ size = 16 }: { size?: number }) => (
|
|||
</svg>
|
||||
);
|
||||
|
||||
export const CpuIcon = ({ size = 16 }: { size?: number }) => (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
style={{ color: 'currentcolor' }}
|
||||
>
|
||||
<path d="M4 12C4 8.22876 4 6.34315 5.17157 5.17157C6.34315 4 8.22876 4 12 4C15.7712 4 17.6569 4 18.8284 5.17157C20 6.34315 20 8.22876 20 12C20 15.7712 20 17.6569 18.8284 18.8284C17.6569 20 15.7712 20 12 20C8.22876 20 6.34315 20 5.17157 18.8284C4 17.6569 4 15.7712 4 12Z" strokeLinejoin="round" />
|
||||
<path d="M9.5 2V4" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M14.5 2V4" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M9.5 20V22" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M14.5 20V22" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M13 9L9 13" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M15 13L13 15" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M22 14.5L20 14.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4 9.5L2 9.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4 14.5L2 14.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M22 9.5L20 9.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const PenIcon = ({ size = 16 }: { size?: number }) => (
|
||||
<svg
|
||||
height={size}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
import { toast } from 'sonner';
|
||||
import { useLocalStorage, useWindowSize } from 'usehooks-ts';
|
||||
|
||||
import { ArrowUpIcon, PaperclipIcon, StopIcon } from './icons';
|
||||
import { ArrowUpIcon, PaperclipIcon, CpuIcon, StopIcon, ChevronDownIcon } from './icons';
|
||||
import { PreviewAttachment } from './preview-attachment';
|
||||
import { Button } from './ui/button';
|
||||
import { SuggestedActions } from './suggested-actions';
|
||||
|
|
@ -26,10 +26,10 @@ import {
|
|||
PromptInputTools,
|
||||
PromptInputSubmit,
|
||||
PromptInputModelSelect,
|
||||
PromptInputModelSelectTrigger,
|
||||
PromptInputModelSelectContent,
|
||||
} from './elements/prompt-input';
|
||||
import { SelectItem } from '@/components/ui/select';
|
||||
import * as SelectPrimitive from '@radix-ui/react-select';
|
||||
import equal from 'fast-deep-equal';
|
||||
import type { UseChatHelpers } from '@ai-sdk/react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
|
@ -352,14 +352,14 @@ function PureMultimodalInput({
|
|||
minHeight={44}
|
||||
maxHeight={200}
|
||||
disableAutoResize={true}
|
||||
className='grow resize-none border-0! border-none! bg-transparent px-2 py-3 text-sm outline-none ring-0 [-ms-overflow-style:none] [scrollbar-width:none] placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 sm:px-3 [&::-webkit-scrollbar]:hidden'
|
||||
className='grow resize-none border-0! border-none! bg-transparent px-2 pt-1 pb-3 ml-1 text-sm outline-none ring-0 [-ms-overflow-style:none] [scrollbar-width:none] placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 [&::-webkit-scrollbar]:hidden'
|
||||
rows={1}
|
||||
autoFocus
|
||||
/>{' '}
|
||||
<Context {...contextProps} className="mr-1.5" />
|
||||
<Context {...contextProps} className="mr-0.5 mt-1" />
|
||||
</div>
|
||||
<PromptInputToolbar className='!border-top-0 border-t-0! px-2 py-2 shadow-none dark:border-0 dark:border-transparent!'>
|
||||
<PromptInputTools className="gap-1 sm:gap-2">
|
||||
<PromptInputTools className="gap-0 sm:gap-0.5">
|
||||
<AttachmentsButton
|
||||
fileInputRef={fileInputRef}
|
||||
status={status}
|
||||
|
|
@ -374,7 +374,7 @@ function PureMultimodalInput({
|
|||
<PromptInputSubmit
|
||||
status={status}
|
||||
disabled={!input.trim() || uploadQueue.length > 0}
|
||||
className="size-7 rounded-full bg-primary p-1 text-primary-foreground transition-colors duration-200 hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground"
|
||||
className="size-7 rounded-full bg-primary p-1 text-primary-foreground transition-colors duration-200 hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground -mt-2"
|
||||
>
|
||||
<ArrowUpIcon size={14} />
|
||||
</PromptInputSubmit>
|
||||
|
|
@ -413,7 +413,7 @@ function PureAttachmentsButton({
|
|||
return (
|
||||
<Button
|
||||
data-testid="attachments-button"
|
||||
className='h-fit rounded-md p-1 transition-colors duration-200 hover:bg-muted'
|
||||
className='h-8 rounded-lg p-1 transition-colors hover:bg-accent'
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
fileInputRef.current?.click();
|
||||
|
|
@ -452,18 +452,22 @@ function PureModelSelectorCompact({
|
|||
}
|
||||
}}
|
||||
>
|
||||
<PromptInputModelSelectTrigger
|
||||
<SelectPrimitive.Trigger
|
||||
type="button"
|
||||
className='max-w-[120px] truncate text-xs focus:outline-hidden focus:ring-0 focus:ring-offset-0 focus-visible:ring-0 focus-visible:ring-offset-0 data-[state=closed]:ring-0 data-[state=open]:ring-0 sm:max-w-none'
|
||||
className='flex items-center gap-2 px-2 h-8 rounded-lg border-0 bg-background text-foreground hover:bg-accent transition-colors focus:outline-none focus:ring-0 focus-visible:ring-0 focus-visible:ring-offset-0 shadow-none'
|
||||
>
|
||||
{selectedModel?.name || 'Select model'}
|
||||
</PromptInputModelSelectTrigger>
|
||||
<PromptInputModelSelectContent className="max-w-[90vw] sm:max-w-[400px]">
|
||||
<CpuIcon size={16} />
|
||||
<span className="text-xs font-medium sm:block hidden">{selectedModel?.name}</span>
|
||||
<ChevronDownIcon size={16} />
|
||||
</SelectPrimitive.Trigger>
|
||||
<PromptInputModelSelectContent className="min-w-[260px] p-0">
|
||||
{chatModels.map((model) => (
|
||||
<SelectItem key={model.id} value={model.name}>
|
||||
<div className='flex flex-col items-start gap-1 py-1'>
|
||||
<div className='font-medium text-sm'>{model.name}</div>
|
||||
<div className='line-clamp-2 text-muted-foreground text-xs'>
|
||||
<SelectItem key={model.id} value={model.name} className="px-3 py-2 text-xs">
|
||||
<div className="flex flex-col min-w-0 flex-1">
|
||||
<div className="font-medium truncate text-xs">
|
||||
{model.name}
|
||||
</div>
|
||||
<div className="text-[10px] text-muted-foreground truncate leading-tight">
|
||||
{model.description}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ const SelectContent = React.forwardRef<
|
|||
<SelectScrollUpButton />
|
||||
<SelectPrimitive.Viewport
|
||||
className={cn(
|
||||
'p-1',
|
||||
'p-2',
|
||||
position === 'popper' &&
|
||||
'h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)',
|
||||
)}
|
||||
|
|
@ -118,14 +118,14 @@ const SelectItem = React.forwardRef<
|
|||
<SelectPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
|
||||
'relative flex w-full cursor-default select-none items-center rounded-md py-1.5 pr-8 pl-3 text-sm outline-hidden hover:bg-muted/50 focus:bg-muted data-[state=checked]:bg-muted data-disabled:pointer-events-none data-disabled:opacity-50 transition-colors',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<span className="absolute right-3 flex h-4 w-4 items-center justify-center">
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<Check className="h-4 w-4" />
|
||||
<Check className="h-4 w-4 text-foreground" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue