feat: enhance UI components with new border radius and tooltip features

- Added new border radius options (2xl, 3xl) in Tailwind configuration and globals.css.
- Integrated Tooltip component in ChatShareButton and ModelSelector for improved user experience.
- Updated button styles for consistency across components, including NotificationButton and ModelSelector.
- Minor text adjustments for clarity in SourceDetailPanel.
This commit is contained in:
Anish Sarkar 2026-01-20 17:35:08 +05:30
parent 23f1be50f7
commit 1f06794021
6 changed files with 40 additions and 43 deletions

View file

@ -113,6 +113,8 @@
--radius-md: calc(var(--radius) - 2px); --radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius); --radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px); --radius-xl: calc(var(--radius) + 4px);
--radius-2xl: calc(var(--radius) + 8px);
--radius-3xl: calc(var(--radius) + 12px);
--color-sidebar: var(--sidebar); --color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary: var(--sidebar-primary);

View file

@ -8,6 +8,7 @@ import { toast } from "sonner";
import { currentThreadAtom, setThreadVisibilityAtom } from "@/atoms/chat/current-thread.atom"; import { currentThreadAtom, setThreadVisibilityAtom } from "@/atoms/chat/current-thread.atom";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { import {
type ChatVisibility, type ChatVisibility,
type ThreadRecord, type ThreadRecord,
@ -99,34 +100,36 @@ export function ChatShareButton({ thread, onVisibilityChange, className }: ChatS
return ( return (
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild> <Tooltip>
<Button <TooltipTrigger asChild>
variant="ghost" <PopoverTrigger asChild>
size="sm" <Button
className={cn( variant="outline"
"h-7 md:h-9 gap-1 md:gap-2 px-2 md:px-3 rounded-lg md:rounded-xl border border-border/80 bg-background/50 backdrop-blur-sm", size="icon"
"hover:bg-muted/80 hover:border-border/30 transition-all duration-200", className={cn(
"text-xs md:text-sm font-medium text-foreground", "h-8 w-8 md:w-auto md:px-3 md:gap-2 relative bg-muted hover:bg-muted/80 border-0",
"focus-visible:ring-0 focus-visible:ring-offset-0", className
className )}
)} >
> <CurrentIcon className="h-4 w-4" />
<CurrentIcon className="size-3.5 md:size-4 text-muted-foreground" /> <span className="hidden md:inline text-sm">
<span className="hidden md:inline"> {currentVisibility === "PRIVATE" ? "Private" : "Shared"}
{currentVisibility === "PRIVATE" ? "Private" : "Shared"} </span>
</span> </Button>
</Button> </PopoverTrigger>
</PopoverTrigger> </TooltipTrigger>
<TooltipContent>Share settings</TooltipContent>
</Tooltip>
<PopoverContent <PopoverContent
className="w-[280px] md:w-[320px] p-0 rounded-lg md:rounded-xl shadow-lg border-border/60" className="w-[280px] md:w-[320px] p-0 rounded-lg shadow-lg border-border/60"
align="end" align="end"
sideOffset={8} sideOffset={8}
> >
<div className="p-1.5 space-y-1"> <div className="p-1.5 space-y-1">
{/* Updating overlay */} {/* Updating overlay */}
{isUpdating && ( {isUpdating && (
<div className="absolute inset-0 z-10 flex items-center justify-center bg-background/80 backdrop-blur-sm rounded-xl"> <div className="absolute inset-0 z-10 flex items-center justify-center bg-background/80 backdrop-blur-sm rounded-lg">
<div className="flex items-center gap-2 text-sm text-muted-foreground"> <div className="flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" /> <Loader2 className="size-4 animate-spin" />
<span>Updating</span> <span>Updating</span>
@ -169,11 +172,6 @@ export function ChatShareButton({ thread, onVisibilityChange, className }: ChatS
<span className={cn("text-sm font-medium", isSelected && "text-primary")}> <span className={cn("text-sm font-medium", isSelected && "text-primary")}>
{option.label} {option.label}
</span> </span>
{isSelected && (
<span className="text-[10px] px-1.5 py-0.5 rounded-full bg-primary/10 text-primary font-medium">
Current
</span>
)}
</div> </div>
<p className="text-xs text-muted-foreground mt-0.5 leading-snug"> <p className="text-xs text-muted-foreground mt-0.5 leading-snug">
{option.description} {option.description}

View file

@ -170,31 +170,27 @@ export function ModelSelector({ onEdit, onAddNew, className }: ModelSelectorProp
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button <Button
variant="ghost" variant="outline"
size="sm" size="sm"
role="combobox" role="combobox"
aria-expanded={open} aria-expanded={open}
className={cn( className={cn(
"h-7 md:h-9 gap-1 md:gap-2 px-2 md:px-3 rounded-lg md:rounded-xl border border-border/80 bg-background/50 backdrop-blur-sm", "h-8 gap-2 px-3 text-sm border-border/60",
"hover:bg-muted/80 hover:border-border/30 transition-all duration-200",
"text-xs md:text-sm font-medium text-foreground",
"focus-visible:ring-0 focus-visible:ring-offset-0",
className className
)} )}
> >
{isLoading ? ( {isLoading ? (
<> <>
<Loader2 className="size-3.5 md:size-4 animate-spin text-muted-foreground" /> <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
<span className="text-muted-foreground hidden md:inline">Loading...</span> <span className="text-muted-foreground hidden md:inline">Loading...</span>
<span className="text-muted-foreground md:hidden">Load...</span>
</> </>
) : currentConfig ? ( ) : currentConfig ? (
<> <>
{getProviderIcon(currentConfig.provider)} {getProviderIcon(currentConfig.provider)}
<span className="max-w-[80px] md:max-w-[150px] truncate">{currentConfig.name}</span> <span className="max-w-[100px] md:max-w-[150px] truncate hidden md:inline">{currentConfig.name}</span>
<Badge <Badge
variant="secondary" variant="secondary"
className="ml-0.5 md:ml-1 text-[9px] md:text-[10px] px-1 md:px-1.5 py-0 h-3.5 md:h-4 bg-muted/80" className="ml-1 text-[10px] px-1.5 py-0 h-4 bg-muted/80"
> >
{currentConfig.model_name.split("/").pop()?.slice(0, 10) || {currentConfig.model_name.split("/").pop()?.slice(0, 10) ||
currentConfig.model_name.slice(0, 10)} currentConfig.model_name.slice(0, 10)}
@ -202,27 +198,26 @@ export function ModelSelector({ onEdit, onAddNew, className }: ModelSelectorProp
</> </>
) : ( ) : (
<> <>
<Bot className="size-3.5 md:size-4 text-muted-foreground" /> <Bot className="h-4 w-4 text-muted-foreground" />
<span className="text-muted-foreground hidden md:inline">Select Model</span> <span className="text-muted-foreground hidden md:inline">Select Model</span>
<span className="text-muted-foreground md:hidden">Model</span>
</> </>
)} )}
<ChevronDown className="size-3 md:size-3.5 text-muted-foreground ml-1 shrink-0" /> <ChevronDown className="h-3.5 w-3.5 text-muted-foreground ml-1 shrink-0" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent <PopoverContent
className="w-[280px] md:w-[360px] p-0 rounded-lg md:rounded-xl shadow-lg border-border/60" className="w-[280px] md:w-[360px] p-0 rounded-lg shadow-lg border-border/60"
align="start" align="start"
sideOffset={8} sideOffset={8}
> >
<Command <Command
shouldFilter={false} shouldFilter={false}
className="rounded-xl relative [&_[data-slot=command-input-wrapper]]:border-0 [&_[data-slot=command-input-wrapper]]:px-0 [&_[data-slot=command-input-wrapper]]:gap-2" className="rounded-lg relative [&_[data-slot=command-input-wrapper]]:border-0 [&_[data-slot=command-input-wrapper]]:px-0 [&_[data-slot=command-input-wrapper]]:gap-2"
> >
{/* Switching overlay */} {/* Switching overlay */}
{isSwitching && ( {isSwitching && (
<div className="absolute inset-0 z-10 flex items-center justify-center bg-background/80 backdrop-blur-sm rounded-xl"> <div className="absolute inset-0 z-10 flex items-center justify-center bg-background/80 backdrop-blur-sm rounded-lg">
<div className="flex items-center gap-2 text-sm text-muted-foreground"> <div className="flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" /> <Loader2 className="size-4 animate-spin" />
<span>Switching model...</span> <span>Switching model...</span>

View file

@ -4,7 +4,6 @@ import { useQuery } from "@tanstack/react-query";
import { import {
BookOpen, BookOpen,
ChevronDown, ChevronDown,
ChevronUp,
ExternalLink, ExternalLink,
FileText, FileText,
Hash, Hash,
@ -387,7 +386,7 @@ export function SourceDetailPanel({
<div className="absolute inset-0 rounded-full bg-primary/20 blur-xl" /> <div className="absolute inset-0 rounded-full bg-primary/20 blur-xl" />
<Loader2 className="h-12 w-12 animate-spin text-primary relative" /> <Loader2 className="h-12 w-12 animate-spin text-primary relative" />
</div> </div>
<p className="text-sm text-muted-foreground font-medium">Loading document...</p> <p className="text-sm text-muted-foreground font-medium">Loading document</p>
</motion.div> </motion.div>
</div> </div>
)} )}

View file

@ -31,7 +31,7 @@ export function NotificationButton() {
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button variant="outline" size="icon" className="h-8 w-8 relative"> <Button variant="outline" size="icon" className="h-8 w-8 relative border-0">
<Bell className="h-4 w-4" /> <Bell className="h-4 w-4" />
{unreadCount > 0 && ( {unreadCount > 0 && (
<span <span

View file

@ -52,6 +52,9 @@ module.exports = {
}, },
}, },
borderRadius: { borderRadius: {
"3xl": "calc(var(--radius) + 12px)",
"2xl": "calc(var(--radius) + 8px)",
xl: "calc(var(--radius) + 4px)",
lg: "var(--radius)", lg: "var(--radius)",
md: "calc(var(--radius) - 2px)", md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)", sm: "calc(var(--radius) - 4px)",