style: Adjust UI element and text sizes for improved responsiveness and visual consistency across various components.

This commit is contained in:
Anish Sarkar 2025-12-28 23:59:01 +05:30
parent 3bea989868
commit 1d5ee45bd9
9 changed files with 145 additions and 149 deletions

View file

@ -51,11 +51,11 @@ export default function AddSourcesPage() {
>
{/* Header */}
<div className="text-center space-y-2">
<h1 className="text-4xl font-bold tracking-tight flex items-center justify-center gap-3">
<Database className="h-8 w-8" />
<h1 className="text-2xl sm:text-4xl font-bold tracking-tight flex items-center justify-center gap-3">
<Database className="h-6 w-6 sm:h-8 sm:w-8" />
Add Sources
</h1>
<p className="text-muted-foreground text-lg">Add your sources to your search space</p>
<p className="text-muted-foreground text-sm sm:text-lg">Add your sources to your search space</p>
</div>
{/* Tabs */}

View file

@ -1,29 +1,15 @@
"use client";
import { useQuery } from "@tanstack/react-query";
import {
type ColumnDef,
type ColumnFiltersState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
type SortingState,
useReactTable,
} from "@tanstack/react-table";
import { useAtomValue } from "jotai";
import {
ArrowLeft,
Calendar,
Check,
ChevronDown,
ChevronUp,
Clock,
Copy,
Crown,
Edit2,
ExternalLink,
Hash,
Link2,
LinkIcon,
@ -32,7 +18,6 @@ import {
Plus,
RefreshCw,
Search,
Settings,
Shield,
ShieldCheck,
Trash2,
@ -40,7 +25,6 @@ import {
UserMinus,
UserPlus,
Users,
X,
} from "lucide-react";
import { motion } from "motion/react";
import { useParams, useRouter } from "next/navigation";
@ -90,7 +74,6 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
@ -105,7 +88,6 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import {
Table,
TableBody,
@ -295,7 +277,7 @@ export default function TeamManagementPage() {
staleTime: 5 * 60 * 1000,
});
const { data: permissionsData, isLoading: permissionsLoading } = useAtomValue(permissionsAtom);
const { data: permissionsData } = useAtomValue(permissionsAtom);
const permissions = permissionsData?.permissions || [];
const groupedPermissions = useMemo(() => {
const groups: Record<string, typeof permissions> = {};
@ -308,8 +290,6 @@ export default function TeamManagementPage() {
return groups;
}, [permissions]);
const canManageMembers = hasPermission("members:view");
const canManageRoles = hasPermission("roles:read");
const canInvite = hasPermission("members:invite");
const handleRefresh = useCallback(async () => {
@ -339,40 +319,40 @@ export default function TeamManagementPage() {
variants={staggerContainer}
className="min-h-screen bg-background"
>
<div className="container max-w-7xl mx-auto p-6 lg:p-8">
<div className="container max-w-7xl mx-auto p-4 md:p-6 lg:p-8">
<motion.div variants={fadeInUp} className="space-y-8">
{/* Header */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div className="flex items-start space-x-3 md:items-center md:space-x-4">
<button
onClick={() => router.push(`/dashboard/${searchSpaceId}`)}
className="flex items-center justify-center h-10 w-10 rounded-lg bg-primary/10 hover:bg-primary/20 transition-colors"
className="flex items-center justify-center h-9 w-9 md:h-10 md:w-10 rounded-lg bg-primary/10 hover:bg-primary/20 transition-colors shrink-0"
aria-label="Back to Dashboard"
type="button"
>
<ArrowLeft className="h-5 w-5 text-primary" />
<ArrowLeft className="h-4 w-4 md:h-5 md:w-5 text-primary" />
</button>
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-gradient-to-br from-primary/20 to-primary/5 ring-1 ring-primary/10">
<Users className="h-6 w-6 text-primary" />
<div className="flex h-10 w-10 md:h-12 md:w-12 items-center justify-center rounded-xl bg-gradient-to-br from-primary/20 to-primary/5 ring-1 ring-primary/10 shrink-0">
<Users className="h-5 w-5 md:h-6 md:w-6 text-primary" />
</div>
<div className="space-y-1">
<h1 className="text-3xl font-bold tracking-tight bg-gradient-to-r from-foreground to-foreground/70 bg-clip-text">
<div className="space-y-1 min-w-0">
<h1 className="text-2xl md:text-3xl font-bold tracking-tight bg-gradient-to-r from-foreground to-foreground/70 bg-clip-text">
Team Management
</h1>
<p className="text-muted-foreground">
<p className="text-xs md:text-sm text-muted-foreground">
Manage members, roles, and invite links for your search space
</p>
</div>
</div>
<div className="flex items-center gap-2">
<Button onClick={handleRefresh} variant="outline" size="sm" className="gap-2">
<Button onClick={handleRefresh} variant="outline" size="sm" className="gap-2 w-full md:w-auto">
<RefreshCw className="h-4 w-4" />
Refresh
</Button>
</div>
</div>
<Separator className="bg-gradient-to-r from-border via-border/50 to-transparent" />
</div>
{/* Summary Cards */}
@ -435,42 +415,46 @@ export default function TeamManagementPage() {
{/* Tabs Content */}
<Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-6">
<div className="flex items-center justify-between">
<TabsList className="bg-muted/50 p-1">
<TabsTrigger value="members" className="gap-2 data-[state=active]:bg-background">
<Users className="h-4 w-4" />
<span>Members</span>
<Badge variant="secondary" className="ml-1 text-xs">
{members.length}
</Badge>
</TabsTrigger>
<TabsTrigger value="roles" className="gap-2 data-[state=active]:bg-background">
<Shield className="h-4 w-4" />
<span>Roles</span>
<Badge variant="secondary" className="ml-1 text-xs">
{roles.length}
</Badge>
</TabsTrigger>
<TabsTrigger value="invites" className="gap-2 data-[state=active]:bg-background">
<LinkIcon className="h-4 w-4" />
<span>Invites</span>
<Badge variant="secondary" className="ml-1 text-xs">
{invites.filter((i) => i.is_active).length}
</Badge>
</TabsTrigger>
</TabsList>
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div className="overflow-x-auto pb-1 md:pb-0">
<TabsList className="bg-muted/50 p-1 w-full md:w-fit grid grid-cols-3 md:flex">
<TabsTrigger value="members" className="gap-1.5 md:gap-2 data-[state=active]:bg-background whitespace-nowrap w-full text-xs md:text-sm flex-1">
<Users className="h-4 w-4 hidden md:block" />
<span>Members</span>
<Badge variant="secondary" className="ml-1 text-xs">
{members.length}
</Badge>
</TabsTrigger>
<TabsTrigger value="roles" className="gap-1.5 md:gap-2 data-[state=active]:bg-background whitespace-nowrap w-full text-xs md:text-sm flex-1">
<Shield className="h-4 w-4 hidden md:block" />
<span>Roles</span>
<Badge variant="secondary" className="ml-1 text-xs">
{roles.length}
</Badge>
</TabsTrigger>
<TabsTrigger value="invites" className="gap-1.5 md:gap-2 data-[state=active]:bg-background whitespace-nowrap w-full text-xs md:text-sm flex-1">
<LinkIcon className="h-4 w-4 hidden md:block" />
<span>Invites</span>
<Badge variant="secondary" className="ml-1 text-xs">
{invites.filter((i) => i.is_active).length}
</Badge>
</TabsTrigger>
</TabsList>
</div>
{activeTab === "invites" && canInvite && (
<CreateInviteDialog
roles={roles}
onCreateInvite={handleCreateInvite}
searchSpaceId={searchSpaceId}
className="w-full md:w-auto"
/>
)}
{activeTab === "roles" && hasPermission("roles:create") && (
<CreateRoleDialog
groupedPermissions={groupedPermissions}
onCreateRole={handleCreateRole}
className="w-full md:w-auto"
/>
)}
</div>
@ -533,8 +517,6 @@ function MembersTab({
canManageRoles: boolean;
canRemove: boolean;
}) {
const [sorting, setSorting] = useState<SortingState>([]);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const [searchQuery, setSearchQuery] = useState("");
const filteredMembers = useMemo(() => {
@ -575,13 +557,13 @@ function MembersTab({
</div>
{/* Members List */}
<div className="rounded-lg border bg-card overflow-hidden">
<div className="rounded-lg border bg-card overflow-x-auto">
<Table>
<TableHeader>
<TableRow className="bg-muted/50">
<TableHead className="w-[300px]">Member</TableHead>
<TableHead>Role</TableHead>
<TableHead>Joined</TableHead>
<TableHead className="w-auto md:w-[300px] px-2 md:px-4">Member</TableHead>
<TableHead className="px-2 md:px-4">Role</TableHead>
<TableHead className="hidden md:table-cell">Joined</TableHead>
<TableHead className="text-right">Actions</TableHead>
</TableRow>
</TableHeader>
@ -604,11 +586,11 @@ function MembersTab({
transition={{ delay: index * 0.05 }}
className="group border-b transition-colors hover:bg-muted/50"
>
<TableCell>
<div className="flex items-center gap-3">
<TableCell className="py-2 px-2 md:py-4 md:px-4 align-middle">
<div className="flex items-center gap-1.5 md:gap-3">
<div className="relative">
<div className="h-10 w-10 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 flex items-center justify-center ring-2 ring-background">
<User className="h-5 w-5 text-primary" />
<div className="h-8 w-8 md:h-10 md:w-10 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 flex items-center justify-center ring-2 ring-background">
<User className="h-4 w-4 md:h-5 md:w-5 text-primary" />
</div>
{member.is_owner && (
<div className="absolute -top-1 -right-1 h-5 w-5 rounded-full bg-amber-500 flex items-center justify-center ring-2 ring-background">
@ -616,12 +598,14 @@ function MembersTab({
</div>
)}
</div>
<div>
<p className="font-medium">{member.user_email || "Unknown"}</p>
<div className="min-w-0">
<p className="font-medium text-xs md:text-sm truncate">
{member.user_email || "Unknown"}
</p>
{member.is_owner && (
<Badge
variant="outline"
className="text-xs mt-1 bg-amber-500/10 text-amber-600 border-amber-500/20"
className="text-[10px] md:text-xs mt-0.5 md:mt-1 bg-amber-500/10 text-amber-600 border-amber-500/20 hidden md:inline-flex"
>
Owner
</Badge>
@ -629,7 +613,7 @@ function MembersTab({
</div>
</div>
</TableCell>
<TableCell>
<TableCell className="py-2 px-2 md:py-4 md:px-4 align-middle">
{canManageRoles && !member.is_owner ? (
<Select
value={member.role_id?.toString() || "none"}
@ -637,7 +621,7 @@ function MembersTab({
onUpdateRole(member.id, value === "none" ? null : Number(value))
}
>
<SelectTrigger className="w-[180px]">
<SelectTrigger className="w-full md:w-[180px] h-8 md:h-10 text-xs md:text-sm">
<SelectValue placeholder="Select role" />
</SelectTrigger>
<SelectContent>
@ -653,19 +637,19 @@ function MembersTab({
</SelectContent>
</Select>
) : (
<Badge variant="secondary" className="gap-1">
<Shield className="h-3 w-3" />
<Badge variant="secondary" className="gap-1 text-[10px] md:text-xs py-0 md:py-0.5">
<Shield className="h-2.5 w-2.5 md:h-3 md:w-3" />
{member.role?.name || "No role"}
</Badge>
)}
</TableCell>
<TableCell>
<TableCell className="hidden md:table-cell">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Calendar className="h-4 w-4" />
{new Date(member.joined_at).toLocaleDateString()}
</div>
</TableCell>
<TableCell className="text-right">
<TableCell className="text-right py-2 px-2 md:py-4 md:px-4 align-middle">
{canRemove && !member.is_owner && (
<AlertDialog>
<AlertDialogTrigger asChild>
@ -962,11 +946,11 @@ function InvitesTab({
className={cn("relative overflow-hidden transition-all", isInactive && "opacity-60")}
>
<CardContent className="p-4">
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-4 flex-1 min-w-0">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
<div className="flex items-start md:items-center gap-4 flex-1 min-w-0">
<div
className={cn(
"h-12 w-12 rounded-xl flex items-center justify-center shrink-0",
"h-10 w-10 md:h-12 md:w-12 rounded-xl flex items-center justify-center shrink-0",
invite.is_active && !isExpired && !isMaxedOut
? "bg-emerald-500/20"
: "bg-muted"
@ -974,7 +958,7 @@ function InvitesTab({
>
<Link2
className={cn(
"h-6 w-6",
"h-5 w-5 md:h-6 md:w-6",
invite.is_active && !isExpired && !isMaxedOut
? "text-emerald-600"
: "text-muted-foreground"
@ -991,7 +975,7 @@ function InvitesTab({
)}
{isMaxedOut && (
<Badge variant="secondary" className="text-xs">
Max uses reached
Maxed
</Badge>
)}
{!invite.is_active && !isExpired && !isMaxedOut && (
@ -1000,44 +984,44 @@ function InvitesTab({
</Badge>
)}
</div>
<div className="flex items-center gap-4 mt-1 text-sm text-muted-foreground flex-wrap">
<div className="flex flex-col md:flex-row md:items-center gap-2 md:gap-4 mt-1 text-sm text-muted-foreground">
<span className="flex items-center gap-1">
<Shield className="h-3 w-3" />
{invite.role?.name || "Default role"}
</span>
<span className="flex items-center gap-1">
<Hash className="h-3 w-3" />
{invite.uses_count} uses
{invite.max_uses && ` / ${invite.max_uses}`}
{invite.uses_count}
{invite.max_uses ? ` / ${invite.max_uses} uses` : " uses"}
</span>
{invite.expires_at && (
<span className="flex items-center gap-1">
<Clock className="h-3 w-3" />
{isExpired
? "Expired"
: `Expires ${new Date(invite.expires_at).toLocaleDateString()}`}
: `Exp: ${new Date(invite.expires_at).toLocaleDateString()}`}
</span>
)}
</div>
</div>
</div>
<div className="flex items-center gap-2 shrink-0">
<div className="flex items-center gap-2 shrink-0 self-end md:self-auto">
<Button
variant="outline"
size="sm"
className="gap-2"
className="gap-2 flex-1 md:flex-none"
onClick={() => copyInviteLink(invite)}
disabled={Boolean(isInactive)}
>
{copiedId === invite.id ? (
<>
<Check className="h-4 w-4 text-emerald-500" />
Copied!
<span className="md:inline">Copied!</span>
</>
) : (
<>
<Copy className="h-4 w-4" />
Copy Link
<span className="md:inline">Copy</span>
</>
)}
</Button>
@ -1088,11 +1072,11 @@ function InvitesTab({
function CreateInviteDialog({
roles,
onCreateInvite,
searchSpaceId,
className,
}: {
roles: Role[];
onCreateInvite: (data: CreateInviteRequest["data"]) => Promise<Invite>;
searchSpaceId: number;
className?: string;
}) {
const [open, setOpen] = useState(false);
const [creating, setCreating] = useState(false);
@ -1142,12 +1126,12 @@ function CreateInviteDialog({
return (
<Dialog open={open} onOpenChange={(v) => (v ? setOpen(true) : handleClose())}>
<DialogTrigger asChild>
<Button className="gap-2">
<Button className={cn("gap-2", className)}>
<UserPlus className="h-4 w-4" />
Create Invite
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogContent className="w-[92vw] max-w-[92vw] sm:max-w-md p-4 md:p-6">
{createdInvite ? (
<>
<DialogHeader>
@ -1159,7 +1143,7 @@ function CreateInviteDialog({
Share this link to invite people to your search space.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-3 py-2 md:py-4">
<div className="flex items-center gap-2 p-3 bg-muted rounded-lg">
<code className="flex-1 min-w-0 text-sm break-all">
{window.location.origin}/invite/{createdInvite.invite_code}
@ -1203,7 +1187,7 @@ function CreateInviteDialog({
Create a link to invite people to this search space.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-3 py-2 md:py-4">
<div className="space-y-2">
<Label htmlFor="invite-name">Name (optional)</Label>
<Input
@ -1234,7 +1218,7 @@ function CreateInviteDialog({
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="flex flex-col md:grid md:grid-cols-2 gap-3 md:gap-4">
<div className="space-y-2">
<Label htmlFor="max-uses">Max uses (optional)</Label>
<Input
@ -1301,9 +1285,11 @@ function CreateInviteDialog({
function CreateRoleDialog({
groupedPermissions,
onCreateRole,
className,
}: {
groupedPermissions: Record<string, { value: string; name: string; category: string }[]>;
onCreateRole: (data: CreateRoleRequest["data"]) => Promise<Role>;
className?: string;
}) {
const [open, setOpen] = useState(false);
const [creating, setCreating] = useState(false);
@ -1358,20 +1344,20 @@ function CreateRoleDialog({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className="gap-2">
<Button className={cn("gap-2", className)}>
<Plus className="h-4 w-4" />
Create Role
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-xl">
<DialogContent className="w-[92vw] max-w-[92vw] sm:max-w-xl p-4 md:p-6">
<DialogHeader>
<DialogTitle>Create Custom Role</DialogTitle>
<DialogDescription>
<DialogDescription className="text-xs md:text-sm">
Define a new role with specific permissions for this search space.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-3 py-2 md:py-4">
<div className="flex flex-col md:grid md:grid-cols-2 gap-3 md:gap-4">
<div className="space-y-2">
<Label htmlFor="role-name">Role Name *</Label>
<Input

View file

@ -69,7 +69,7 @@ export default function InferenceParamsEditor({ params, setParams }: InferencePa
<div className="space-y-6 p-2 sm:p-0">
<div className="grid grid-cols-1 gap-4 md:grid-cols-[1fr_1fr_auto] md:gap-3 items-end">
<div className="flex flex-col space-y-1">
<Label htmlFor="param-key" className="text-sm font-medium">
<Label htmlFor="param-key" className="text-xs sm:text-sm font-medium">
Parameter Key
</Label>
<Select value={selectedKey} onValueChange={setSelectedKey}>
@ -87,7 +87,7 @@ export default function InferenceParamsEditor({ params, setParams }: InferencePa
</div>
<div className="flex flex-col space-y-1">
<Label htmlFor="param-value" className="text-sm font-medium">
<Label htmlFor="param-value" className="text-xs sm:text-sm font-medium">
Value
</Label>
<Input
@ -100,11 +100,11 @@ export default function InferenceParamsEditor({ params, setParams }: InferencePa
</div>
<Button
className="w-full md:w-auto h-10 mt-0"
className="w-full md:w-auto h-9 sm:h-10 mt-0 text-xs sm:text-sm"
onClick={handleAdd}
disabled={!selectedKey || value === ""}
>
<Plus className="w-4 h-4 mr-2" /> Add Parameter
<Plus className="w-3.5 h-3.5 sm:w-4 sm:h-4 mr-2" /> Add Parameter
</Button>
</div>

View file

@ -184,7 +184,7 @@ export function ModelConfigSidebar({
<Bot className="size-5 text-primary" />
</div>
<div>
<h2 className="text-lg font-semibold">{getTitle()}</h2>
<h2 className="text-base sm:text-lg font-semibold">{getTitle()}</h2>
<div className="flex items-center gap-2 mt-0.5">
{isGlobal ? (
<Badge variant="secondary" className="gap-1 text-xs">
@ -207,9 +207,10 @@ export function ModelConfigSidebar({
variant="ghost"
size="icon"
onClick={() => onOpenChange(false)}
className="rounded-xl hover:bg-destructive/10 hover:text-destructive"
className="h-8 w-8 rounded-full"
>
<X className="size-5" />
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</Button>
</div>

View file

@ -352,9 +352,9 @@ export function SourceDetailPanel({
size="icon"
variant="ghost"
onClick={() => onOpenChange(false)}
className="rounded-xl h-10 w-10 hover:bg-destructive/10 hover:text-destructive transition-colors"
className="h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</Button>
</div>

View file

@ -156,8 +156,8 @@ export function LLMConfigForm({
<form onSubmit={form.handleSubmit(handleFormSubmit)} className="space-y-6">
{/* System Instructions & Citations Section */}
<div className="space-y-4">
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<MessageSquareQuote className="h-4 w-4" />
<div className="flex items-center gap-2 text-xs sm:text-sm font-medium text-muted-foreground">
<MessageSquareQuote className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
System Instructions
</div>
@ -168,7 +168,7 @@ export function LLMConfigForm({
render={({ field }) => (
<FormItem>
<div className="flex items-center justify-between">
<FormLabel>Instructions for the AI</FormLabel>
<FormLabel className="text-xs sm:text-sm">Instructions for the AI</FormLabel>
{defaultInstructions && (
<Button
type="button"
@ -177,7 +177,7 @@ export function LLMConfigForm({
onClick={() =>
field.onChange(defaultInstructions.default_system_instructions)
}
className="h-7 text-xs text-muted-foreground hover:text-foreground"
className="h-7 text-[10px] sm:text-xs text-muted-foreground hover:text-foreground"
>
Reset to Default
</Button>
@ -187,11 +187,11 @@ export function LLMConfigForm({
<Textarea
placeholder="Enter system instructions for the AI..."
rows={6}
className="font-mono text-xs resize-none"
className="font-mono text-[11px] sm:text-xs resize-none"
{...field}
/>
</FormControl>
<FormDescription className="text-xs">
<FormDescription className="text-[10px] sm:text-xs">
Use {"{resolved_today}"} to include today's date dynamically
</FormDescription>
<FormMessage />
@ -206,8 +206,8 @@ export function LLMConfigForm({
render={({ field }) => (
<FormItem className="flex items-center justify-between rounded-lg border p-3 bg-muted/30">
<div className="space-y-0.5">
<FormLabel className="text-sm font-medium">Enable Citations</FormLabel>
<FormDescription className="text-xs">
<FormLabel className="text-xs sm:text-sm font-medium">Enable Citations</FormLabel>
<FormDescription className="text-[10px] sm:text-xs">
Include [citation:id] references to source documents
</FormDescription>
</div>
@ -223,8 +223,8 @@ export function LLMConfigForm({
{/* Model Configuration Section */}
<div className="space-y-4">
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<Bot className="h-4 w-4" />
<div className="flex items-center gap-2 text-xs sm:text-sm font-medium text-muted-foreground">
<Bot className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
Model Configuration
</div>
@ -235,7 +235,7 @@ export function LLMConfigForm({
name="name"
render={({ field }) => (
<FormItem>
<FormLabel className="flex items-center gap-2">
<FormLabel className="flex items-center gap-2 text-xs sm:text-sm">
<Sparkles className="h-3.5 w-3.5 text-violet-500" />
Configuration Name
</FormLabel>
@ -256,7 +256,7 @@ export function LLMConfigForm({
name="description"
render={({ field }) => (
<FormItem>
<FormLabel className="text-muted-foreground">
<FormLabel className="text-muted-foreground text-xs sm:text-sm">
Description
<Badge variant="outline" className="ml-2 text-[10px]">
Optional
@ -277,7 +277,7 @@ export function LLMConfigForm({
name="provider"
render={({ field }) => (
<FormItem>
<FormLabel>LLM Provider</FormLabel>
<FormLabel className="text-xs sm:text-sm">LLM Provider</FormLabel>
<Select value={field.value} onValueChange={handleProviderChange}>
<FormControl>
<SelectTrigger className="transition-all focus:ring-violet-500/50">
@ -315,7 +315,7 @@ export function LLMConfigForm({
name="custom_provider"
render={({ field }) => (
<FormItem>
<FormLabel>Custom Provider Name</FormLabel>
<FormLabel className="text-xs sm:text-sm">Custom Provider Name</FormLabel>
<FormControl>
<Input
placeholder="my-custom-provider"
@ -337,7 +337,7 @@ export function LLMConfigForm({
name="model_name"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Model Name</FormLabel>
<FormLabel className="text-xs sm:text-sm">Model Name</FormLabel>
<Popover open={modelComboboxOpen} onOpenChange={setModelComboboxOpen}>
<PopoverTrigger asChild>
<FormControl>
@ -410,7 +410,7 @@ export function LLMConfigForm({
</PopoverContent>
</Popover>
{selectedProvider?.example && (
<FormDescription className="text-xs">
<FormDescription className="text-[10px] sm:text-xs">
Example: {selectedProvider.example}
</FormDescription>
)}
@ -426,7 +426,7 @@ export function LLMConfigForm({
name="api_key"
render={({ field }) => (
<FormItem>
<FormLabel className="flex items-center gap-2">
<FormLabel className="flex items-center gap-2 text-xs sm:text-sm">
<Key className="h-3.5 w-3.5 text-amber-500" />
API Key
</FormLabel>
@ -438,7 +438,7 @@ export function LLMConfigForm({
/>
</FormControl>
{watchProvider === "OLLAMA" && (
<FormDescription className="text-xs">
<FormDescription className="text-[10px] sm:text-xs">
Ollama doesn't require auth enter any value
</FormDescription>
)}
@ -452,7 +452,7 @@ export function LLMConfigForm({
name="api_base"
render={({ field }) => (
<FormItem>
<FormLabel className="flex items-center gap-2">
<FormLabel className="flex items-center gap-2 text-xs sm:text-sm">
API Base URL
{selectedProvider?.apiBase && (
<Badge variant="secondary" className="text-[10px]">
@ -510,8 +510,8 @@ export function LLMConfigForm({
<>
<Separator />
<div className="space-y-4">
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<Sparkles className="h-4 w-4" />
<div className="flex items-center gap-2 text-xs sm:text-sm font-medium text-muted-foreground">
<Sparkles className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
Advanced Parameters
</div>
@ -542,19 +542,19 @@ export function LLMConfigForm({
)}
>
{onCancel && (
<Button type="button" variant="outline" onClick={onCancel} disabled={isSubmitting}>
<Button type="button" variant="outline" onClick={onCancel} disabled={isSubmitting} className="text-xs sm:text-sm h-9 sm:h-10">
Cancel
</Button>
)}
<Button type="submit" disabled={isSubmitting} className="gap-2 min-w-[160px]">
<Button type="submit" disabled={isSubmitting} className="gap-2 min-w-[140px] sm:min-w-[160px] text-xs sm:text-sm h-9 sm:h-10">
{isSubmitting ? (
<>
<Loader2 className="h-4 w-4 animate-spin" />
<Loader2 className="h-3.5 w-3.5 sm:h-4 sm:w-4 animate-spin" />
{mode === "edit" ? "Updating..." : "Creating..."}
</>
) : (
<>
{!compact && <Rocket className="h-4 w-4" />}
{!compact && <Rocket className="h-3.5 w-3.5 sm:h-4 sm:w-4" />}
{submitLabel ?? (mode === "edit" ? "Update Configuration" : "Create Configuration")}
</>
)}

View file

@ -81,7 +81,7 @@ export function ConnectorsTab({ searchSpaceId }: ConnectorsTabProps) {
className="w-full"
>
<div className="flex items-center justify-between space-x-4 p-4">
<h3 className="text-xl font-semibold">{t(category.title)}</h3>
<h3 className="text-lg sm:text-xl font-semibold">{t(category.title)}</h3>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="sm" className="w-9 p-0 hover:bg-muted">
<motion.div

View file

@ -217,7 +217,7 @@ export function DocumentUploadTab({ searchSpaceId }: DocumentUploadTabProps) {
>
<Alert>
<Info className="h-4 w-4" />
<AlertDescription>{t("file_size_limit")}</AlertDescription>
<AlertDescription className="text-xs sm:text-sm">{t("file_size_limit")}</AlertDescription>
</Alert>
<Card className="relative overflow-hidden">
@ -249,7 +249,7 @@ export function DocumentUploadTab({ searchSpaceId }: DocumentUploadTabProps) {
>
<Upload className="h-12 w-12 text-muted-foreground" />
<div className="text-center">
<p className="text-lg font-medium">{t("drag_drop")}</p>
<p className="text-base sm:text-lg font-medium">{t("drag_drop")}</p>
<p className="text-sm text-muted-foreground mt-1">{t("or_browse")}</p>
</div>
</motion.div>
@ -284,8 +284,10 @@ export function DocumentUploadTab({ searchSpaceId }: DocumentUploadTabProps) {
<CardHeader>
<div className="flex items-center justify-between">
<div>
<CardTitle>{t("selected_files", { count: files.length })}</CardTitle>
<CardDescription>
<CardTitle className="text-lg sm:text-2xl">
{t("selected_files", { count: files.length })}
</CardTitle>
<CardDescription className="text-xs sm:text-sm">
{t("total_size")}: {formatFileSize(getTotalFileSize())}
</CardDescription>
</div>
@ -313,7 +315,9 @@ export function DocumentUploadTab({ searchSpaceId }: DocumentUploadTabProps) {
<div className="flex items-center gap-3 flex-1 min-w-0">
<FileType className="h-5 w-5 text-muted-foreground flex-shrink-0" />
<div className="flex-1 min-w-0">
<p className="font-medium truncate">{file.name}</p>
<p className="text-sm sm:text-base font-medium truncate">
{file.name}
</p>
<div className="flex items-center gap-2 mt-1">
<Badge variant="secondary" className="text-xs">
{formatFileSize(file.size)}
@ -361,7 +365,7 @@ export function DocumentUploadTab({ searchSpaceId }: DocumentUploadTabProps) {
animate={{ opacity: 1, y: 0 }}
>
<Button
className="w-full py-6 text-base font-medium"
className="w-full py-4 sm:py-6 text-sm sm:text-base font-medium"
onClick={handleUpload}
disabled={isUploading || files.length === 0}
>

View file

@ -125,17 +125,19 @@ export function YouTubeTab({ searchSpaceId }: YouTubeTabProps) {
>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<CardTitle className="text-lg sm:text-2xl flex items-center gap-2">
<IconBrandYoutube className="h-5 w-5" />
{t("title")}
</CardTitle>
<CardDescription>{t("subtitle")}</CardDescription>
<CardDescription className="text-xs sm:text-sm">{t("subtitle")}</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="video-input">{t("label")}</Label>
<Label htmlFor="video-input" className="text-sm sm:text-base">
{t("label")}
</Label>
<TagInput
id="video-input"
tags={videoTags}
@ -212,14 +214,17 @@ export function YouTubeTab({ searchSpaceId }: YouTubeTabProps) {
<CardFooter className="flex justify-between">
<Button
variant="outline"
size="sm"
onClick={() => router.push(`/dashboard/${searchSpaceId}/documents`)}
className="text-xs sm:text-sm"
>
{t("cancel")}
</Button>
<Button
onClick={handleSubmit}
disabled={isSubmitting || videoTags.length === 0}
className="relative overflow-hidden"
size="sm"
className="relative overflow-hidden text-xs sm:text-sm"
>
{isSubmitting ? (
<>