creating small ui reusable component

This commit is contained in:
Abhimanyu Yadav
2025-05-17 00:01:40 +05:30
parent 2dc038b6c0
commit 34be6a3379
10 changed files with 512 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Plus } from "lucide-react";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
title?: string;
description?: string;
}
const Block: React.FC<Props> = ({ title, description, className, ...rest }) => {
return (
<Button
className={cn(
"group flex h-16 w-full min-w-[7.5rem] items-center justify-start space-x-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-100 disabled:pointer-events-none",
)}
{...rest}
>
<div className="flex flex-1 flex-col items-start gap-0.5">
<span
className={cn(
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
)}
>
{title}
</span>
<span
className={cn(
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
)}
>
{description}
</span>
</div>
<div
className={cn(
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
)}
>
<Plus className="h-5 w-5 text-zinc-50" strokeWidth={2} />
</div>
</Button>
);
};
export default Block;

View File

@@ -0,0 +1,32 @@
import { cn } from "@/lib/utils";
import React, { ButtonHTMLAttributes } from "react";
import { LucideIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
selected?: boolean;
icon?: LucideIcon;
}
const ControlPanel: React.FC<Props> = ({
selected = false,
icon: Icon,
className,
...rest
}) => {
return (
<Button
className={cn(
"flex h-[4.25rem] w-[4.25rem] items-center justify-center whitespace-normal bg-white p-[1.38rem] text-zinc-800 shadow-none hover:cursor-pointer hover:bg-zinc-100 hover:text-zinc-950 focus:ring-0",
selected &&
"bg-violet-50 text-violet-700 hover:cursor-default hover:bg-violet-50 hover:text-violet-700",
className,
)}
{...rest}
>
{Icon && <Icon className="h-6 w-6" strokeWidth={2} />}
</Button>
);
};
export default ControlPanel;

View File

@@ -0,0 +1,43 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { X } from "lucide-react";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
selected?: boolean;
number?: number;
name?: string;
}
const FilterChip: React.FC<Props> = ({
selected = false,
number,
name,
className,
...rest
}) => {
return (
<Button
className={cn(
"group w-fit space-x-1 rounded-[1.5rem] border border-zinc-300 bg-transparent px-[0.625rem] py-[0.375rem] shadow-none hover:bg-zinc-100 focus:ring-0 disabled:pointer-events-none",
)}
{...rest}
>
<span className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-600 group-disabled:text-zinc-400">
{name}
</span>
{selected &&
(number ? (
<span className="flex h-[1.375rem] items-center rounded-[1.25rem] bg-violet-700 p-[0.375rem] text-zinc-50">
{number}
</span>
) : (
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-zinc-600">
<X className="h-4 w-4 rounded-full text-white" strokeWidth={1.25} />
</span>
))}
</Button>
);
};
export default FilterChip;

View File

@@ -0,0 +1,57 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Plus } from "lucide-react";
import Image from "next/image";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
title?: string;
description?: string;
icon_url?: string;
number_of_blocks?: number;
}
const Integration: React.FC<Props> = ({
title,
icon_url,
description,
className,
number_of_blocks,
...rest
}) => {
return (
<Button
className={cn(
"group flex h-16 w-full min-w-[7.5rem] items-center justify-start space-x-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-50 disabled:pointer-events-none",
)}
{...rest}
>
<div className="relative h-[2.625rem] w-[2.625rem] rounded-[0.5rem] bg-white">
{icon_url && (
<Image
src={icon_url}
alt="integration-icon"
fill
className="w-full object-contain group-disabled:opacity-50"
/>
)}
</div>
<div className="w-full">
<div className="flex items-center justify-between gap-2">
<p className="line-clamp-1 flex-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-700 group-disabled:text-zinc-400">
{title}
</p>
<span className="flex h-[1.375rem] w-[1.6875rem] items-center justify-center rounded-[1.25rem] bg-[#f0f0f0] p-1.5 font-sans text-sm leading-[1.375rem] text-zinc-500 group-disabled:text-zinc-400">
{number_of_blocks}
</span>
</div>
<span className="line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400">
{description}
</span>
</div>
</Button>
);
};
export default Integration;

View File

@@ -0,0 +1,64 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Plus } from "lucide-react";
import Image from "next/image";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
title?: string;
description?: string;
icon_url?: string;
}
const IntegrationBlock: React.FC<Props> = ({
title,
icon_url,
description,
className,
...rest
}) => {
return (
<Button
className={cn(
"group flex h-16 w-full min-w-[7.5rem] items-center justify-start gap-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-100 disabled:pointer-events-none",
)}
{...rest}
>
<div className="relative h-[2.625rem] w-[2.625rem] rounded-[0.5rem] bg-white">
{icon_url && (
<Image
src={icon_url}
alt="integration-icon"
fill
className="w-full object-contain group-disabled:opacity-50"
/>
)}
</div>
<div className="flex flex-1 flex-col items-start gap-0.5">
<span
className={cn(
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
)}
>
{title}
</span>
<span
className={cn(
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
)}
>
{description}
</span>
</div>
<div
className={cn(
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
)}
>
<Plus className="h-5 w-5 text-zinc-50" strokeWidth={2} />
</div>
</Button>
);
};
export default IntegrationBlock;

View File

@@ -0,0 +1,41 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import Image from "next/image";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
name?: string;
icon_url?: string;
}
const IntegrationChip: React.FC<Props> = ({
icon_url,
name,
className,
...rest
}) => {
return (
<Button
className={cn(
"flex h-[3.25rem] w-full min-w-[7.5rem] justify-start gap-2 whitespace-normal rounded-[0.5rem] bg-zinc-50 p-2 pr-3 shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-100",
className,
)}
{...rest}
>
{icon_url && (
<Image
src={icon_url}
alt="integration-icon"
className="h-9 w-9"
width={36}
height={36}
/>
)}
<span className="font-sans text-sm font-normal leading-[1.375rem] text-zinc-800">
{name}
</span>
</Button>
);
};
export default IntegrationChip;

View File

@@ -0,0 +1,78 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Plus } from "lucide-react";
import Image from "next/image";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
title?: string;
creator_name?: string;
number_of_runs?: number;
image_url?: string;
}
const MarketplaceAgentBlock: React.FC<Props> = ({
title,
image_url,
creator_name,
number_of_runs,
className,
...rest
}) => {
return (
<Button
className={cn(
"group flex h-[4.375rem] w-full min-w-[7.5rem] items-center justify-start gap-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 p-[0.625rem] pr-[0.875rem] text-start shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-100 disabled:pointer-events-none",
)}
{...rest}
>
<div className="relative h-[3.125rem] w-[5.625rem] overflow-hidden rounded-[0.375rem] bg-white">
{image_url && (
<Image
src={image_url}
alt="integration-icon"
fill
className="w-full object-contain group-disabled:opacity-50"
/>
)}
</div>
<div className="flex flex-1 flex-col items-start gap-0.5">
<span
className={cn(
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
)}
>
{title}
</span>
<div className="flex items-center space-x-2.5">
<span
className={cn(
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
)}
>
By {creator_name}
</span>
<span className="font-sans text-zinc-400"></span>
<span
className={cn(
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
)}
>
{number_of_runs} runs
</span>
</div>
</div>
<div
className={cn(
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
)}
>
<Plus className="h-5 w-5 text-zinc-50" strokeWidth={2} />
</div>
</Button>
);
};
export default MarketplaceAgentBlock;

View File

@@ -0,0 +1,41 @@
// BLOCK MENU TODO: We need to add a better hover state to it; currently it's not in the design either.
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
selected?: boolean;
number?: number;
name?: string;
}
const MenuItem: React.FC<Props> = ({
selected = false,
number,
name,
className,
...rest
}) => {
return (
<Button
className={cn(
"flex h-[2.375rem] w-full justify-between whitespace-normal rounded-[0.5rem] bg-transparent p-2 pl-3 shadow-none hover:bg-transparent focus:ring-0",
selected && "bg-zinc-100 hover:bg-zinc-100",
className,
)}
{...rest}
>
<span className="truncate font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
{name}
</span>
{number && (
<span className="font-sans text-sm font-normal leading-[1.375rem] text-zinc-600">
{number}+
</span>
)}
</Button>
);
};
export default MenuItem;

View File

@@ -0,0 +1,31 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { ArrowUpRight } from "lucide-react";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
content?: string;
}
const SearchHistoryChip: React.FC<Props> = ({
content,
className,
...rest
}) => {
return (
<Button
className={cn(
"h-[2.375rem] space-x-1 whitespace-normal rounded-[1.5rem] bg-zinc-50 py-[0.44rem] pl-[0.38rem] pr-[0.62rem] shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-100",
className,
)}
{...rest}
>
<ArrowUpRight className="h-6 w-6 text-zinc-500" strokeWidth={1.25} />
<span className="font-sans text-sm font-normal leading-[1.375rem] text-zinc-800">
{content}
</span>
</Button>
);
};
export default SearchHistoryChip;

View File

@@ -0,0 +1,79 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Plus } from "lucide-react";
import Image from "next/image";
import React, { ButtonHTMLAttributes } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
title?: string;
edited_time?: string;
version?: number;
image_url?: string;
}
const UGCAgentBlock: React.FC<Props> = ({
title,
image_url,
edited_time,
version,
className,
...rest
}) => {
return (
<Button
className={cn(
"group flex h-[4.375rem] w-full min-w-[7.5rem] items-center justify-start gap-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 p-[0.625rem] pr-[0.875rem] text-start shadow-none hover:bg-zinc-100 focus:ring-0 active:border active:border-zinc-300 active:bg-zinc-100 disabled:pointer-events-none",
)}
{...rest}
>
<div className="relative h-[3.125rem] w-[5.625rem] overflow-hidden rounded-[0.375rem] bg-white">
{image_url && (
<Image
src={image_url}
alt="integration-icon"
fill
className="w-full object-contain group-disabled:opacity-50"
/>
)}
</div>
<div className="flex flex-1 flex-col items-start gap-0.5">
<span
className={cn(
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
)}
>
{title}
</span>
<div className="flex items-center space-x-2.5">
<span
className={cn(
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
)}
>
{/* BLOCK MENU TODO: We need to create a utility to convert the edit time into relative time (e.g., "2 hours ago") */}
Edited on {edited_time}
</span>
<span className="font-sans text-zinc-400"></span>
<span
className={cn(
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
)}
>
Version {version}
</span>
</div>
</div>
<div
className={cn(
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
)}
>
<Plus className="h-5 w-5 text-zinc-50" strokeWidth={2} />
</div>
</Button>
);
};
export default UGCAgentBlock;