Skip to content

Commit

Permalink
Merge pull request #18 from sotayamashita/refactor/claude-specific-co…
Browse files Browse the repository at this point in the history
…mponents

refactor: isolate Claude-specific UI components
  • Loading branch information
sotayamashita authored Dec 30, 2024
2 parents 73d25a4 + d09bf7e commit 7df3b73
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 252 deletions.
2 changes: 0 additions & 2 deletions src/background.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/// <reference types="chrome"/>
console.log("Hello from the background!");

chrome.runtime.onInstalled.addListener((details) => {
console.log("Extension installed:", details);
});
Expand Down
84 changes: 84 additions & 0 deletions src/components/providers/claude/template-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* eslint-disable tailwindcss/no-custom-classname */
import React from "react";
import type { FC } from "react";
import { BookDashed, ChevronDown } from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
import { ClaudeTemplateList } from "@/components/providers/claude/template-list";

interface Template {
title: string;
content: string;
}

interface Props {
templates: Template[];
onTemplateSelect: (template: Template) => void;
onSettingsClick: () => void;
}

export const ClaudeTemplateButton: FC<Props> = ({
templates,
onTemplateSelect,
onSettingsClick,
}) => {
const [open, setOpen] = React.useState(false);
// Chat dialog will be bottom of the page when on claude.ai/chat
// otherwise it will be top of the page when on claude.ai/project/ or claude.ai/chat/new
const dropdownPosition = window.location.pathname.startsWith("/chat/")
? "top"
: "bottom";

return (
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<button
className={cn(
"inline-flex items-center justify-center relative shrink-0",
"ring-offset-2 ring-offset-bg-300 ring-accent-main-100",
"focus-visible:outline-none focus-visible:ring-1",
"disabled:pointer-events-none disabled:opacity-50",
"disabled:shadow-none disabled:drop-shadow-none",
"max-w-full min-w-0 pl-1.5 pr-1 h-7 ml-0.5 mr-1",
"hover:bg-bg-200 hover:border-border-400",
"border-0.5 text-sm rounded-md border-transparent",
"transition text-text-500 hover:text-text-200",
)}
data-testid="template-selector-dropdown"
type="button"
>
<div
className="inline-flex min-w-0 items-center"
data-state={open ? "open" : "closed"}
>
<BookDashed className="mr-1 -translate-y-px" size={16} />
<span className="font-tiempos mr-px flex-1 -translate-y-px truncate">
Choose prompts
</span>
<ChevronDown className="text-text-500/80 ml-1 shrink-0" size={12} />
</div>
</button>
</DropdownMenuTrigger>

<DropdownMenuContent
align="center"
side={dropdownPosition}
className={cn(
"z-50 bg-bg-200 border-0.5 border-border-300 backdrop-blur-xl",
"rounded-lg min-w-[8rem] overflow-hidden p-1 text-text-200",
"shadow-element !bg-bg-200 !rounded-xl w-64 sm:w-[28rem] !z-30",
)}
>
<ClaudeTemplateList
templates={templates}
onTemplateSelect={onTemplateSelect}
onSettingsClick={onSettingsClick}
/>
</DropdownMenuContent>
</DropdownMenu>
);
};
89 changes: 89 additions & 0 deletions src/components/providers/claude/template-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* eslint-disable tailwindcss/no-custom-classname */
import type { FC } from "react";
import { cn } from "@/lib/utils";

interface Template {
title: string;
content: string;
}

interface Props {
templates: Template[];
onTemplateSelect: (template: Template) => void;
onSettingsClick: () => void;
}

export const ClaudeTemplateList: FC<Props> = ({
templates,
onTemplateSelect,
onSettingsClick,
}) => {
return (
<>
<div className="text-text-300 min-h-5 flex-1 items-center justify-between px-1.5 pb-1.5 pt-1 text-xs font-medium sm:flex">
<div className="translate-y-[0.5px]">Choose a template</div>
</div>

<div className="mt-0.5 px-1 pb-1">
<div className="min-h-0">
<div
className={cn(
"overflow-x-visible overflow-y-auto scroll-pb-6 min-h-[0px]",
"[scrollbar-color:hsl(var(--text-500))]",
"scroll-smooth overscroll-contain",
"[&::-webkit-scrollbar]:w-[0.25rem]",
"[&::-webkit-scrollbar-track]:bg-transparent",
"[&::-webkit-scrollbar-thumb]:rounded-[1em]",
"[&::-webkit-scrollbar-thumb]:bg-text-500/80",
"pr-1 sm:mr-1 pb-1 min-h-10 max-h-64",
)}
>
{templates.length === 0 ? (
<div className="text-text-300 px-2 py-1 text-sm">
No templates found
</div>
) : (
templates.map((template, index) => (
<div
key={index}
role="menuitem"
className={cn(
"py-1 px-2 rounded-md cursor-pointer whitespace-nowrap",
"overflow-hidden text-ellipsis grid",
"grid-cols-[minmax(0,_1fr)_auto] gap-2 items-center",
"outline-none select-none pr-0 mb-0.5 line-clamp-2",
"leading-tight hover:bg-bg-300",
)}
onClick={() => onTemplateSelect(template)}
>
<div className="flex items-center justify-between">
<div className="line-clamp-2 flex-1 text-wrap">
{template.title}
</div>
</div>
</div>
))
)}
</div>

<div
role="menuitem"
data-testid="template-selector-open-modal"
className={cn(
"py-1 px-2 rounded-md cursor-pointer whitespace-nowrap",
"overflow-hidden text-ellipsis grid",
"grid-cols-[minmax(0,_1fr)_auto] gap-2 items-center",
"outline-none select-none bg-transparent border border-border-300",
"hover:!bg-accent-main-100 hover:!text-oncolor-100",
"hover:!border-transparent transition mr-1 sm:mr-3 ml-1 mb-1 mt-1",
"!rounded-lg text-center text-sm font-medium",
)}
onClick={onSettingsClick}
>
Create & Edit Templates
</div>
</div>
</div>
</>
);
};
Loading

0 comments on commit 7df3b73

Please sign in to comment.