Browse Source

refactor: simplify template categories and add provider tags

- Change categories from product/style/composition to simple/advanced
- Add provider filter to sidebar (currently shows Gemini)
- Display provider tags on template cards
- Update tests for new category structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 6 months ago
parent
commit
b0ee905c1c
  1. 24
      src/components/quickstart/TemplateCard.tsx
  2. 22
      src/components/quickstart/TemplateExplorerView.tsx
  3. 2
      src/lib/quickstart/__tests__/templates.test.ts
  4. 2
      src/types/quickstart.ts

24
src/components/quickstart/TemplateCard.tsx

@ -20,16 +20,14 @@ interface TemplateCardProps {
} }
const CATEGORY_LABELS: Record<TemplateCategory, string> = { const CATEGORY_LABELS: Record<TemplateCategory, string> = {
product: "Product", simple: "Simple",
style: "Style", advanced: "Advanced",
composition: "Composition",
community: "Community", community: "Community",
}; };
const CATEGORY_COLORS: Record<TemplateCategory, string> = { const CATEGORY_COLORS: Record<TemplateCategory, string> = {
product: "bg-blue-500/20 text-blue-300", simple: "bg-blue-500/20 text-blue-300",
style: "bg-purple-500/20 text-purple-300", advanced: "bg-purple-500/20 text-purple-300",
composition: "bg-green-500/20 text-green-300",
community: "bg-amber-500/20 text-amber-300", community: "bg-amber-500/20 text-amber-300",
}; };
@ -128,6 +126,20 @@ export function TemplateCard({
{template.description} {template.description}
</p> </p>
{/* Provider tags */}
{template.tags.length > 0 && (
<div className="flex flex-wrap gap-1 mt-2">
{template.tags.map((tag) => (
<span
key={tag}
className="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-neutral-700/30 text-neutral-400"
>
{tag}
</span>
))}
</div>
)}
{/* Action row */} {/* Action row */}
<div className="flex justify-end mt-2"> <div className="flex justify-end mt-2">
<button <button

22
src/components/quickstart/TemplateExplorerView.tsx

@ -16,9 +16,8 @@ type CategoryFilter = "all" | TemplateCategory;
const CATEGORY_OPTIONS: { id: CategoryFilter; label: string }[] = [ const CATEGORY_OPTIONS: { id: CategoryFilter; label: string }[] = [
{ id: "all", label: "All" }, { id: "all", label: "All" },
{ id: "product", label: "Product" }, { id: "simple", label: "Simple" },
{ id: "style", label: "Style" }, { id: "advanced", label: "Advanced" },
{ id: "composition", label: "Composition" },
{ id: "community", label: "Community" }, { id: "community", label: "Community" },
]; ];
@ -138,16 +137,13 @@ export function TemplateExplorerView({
if (!matchesSearch) return false; if (!matchesSearch) return false;
} }
// Tags don't apply to community workflows (they don't have tags)
return true; return true;
}); });
}, [communityWorkflows, debouncedSearch, categoryFilter]); }, [communityWorkflows, debouncedSearch, categoryFilter]);
// Collect all unique tags from filtered presets // Collect all unique tags from presets
const availableTags = useMemo(() => { const availableTags = useMemo(() => {
const tags = new Set<string>(); const tags = new Set<string>();
// Get tags from ALL presets (not just filtered) so users can explore
presets.forEach((preset) => { presets.forEach((preset) => {
preset.tags.forEach((tag) => tags.add(tag)); preset.tags.forEach((tag) => tags.add(tag));
}); });
@ -331,22 +327,22 @@ export function TemplateExplorerView({
</div> </div>
</div> </div>
{/* Tags Section */} {/* Provider Tags */}
<div className="space-y-2"> <div className="space-y-2">
<h3 className="text-xs font-medium text-neutral-500 uppercase tracking-wider"> <h3 className="text-xs font-medium text-neutral-500 uppercase tracking-wider">
Tags Provider
</h3> </h3>
<div className="flex flex-wrap gap-1"> <div className="flex flex-col gap-1">
{availableTags.map((tag) => ( {availableTags.map((tag) => (
<button <button
key={tag} key={tag}
onClick={() => toggleTag(tag)} onClick={() => toggleTag(tag)}
className={` className={`
px-2 py-1 text-[10px] font-medium rounded transition-colors px-3 py-1.5 text-xs font-medium rounded-md text-left transition-colors
${ ${
selectedTags.has(tag) selectedTags.has(tag)
? "bg-blue-500/30 text-blue-300 border border-blue-500/50" ? "bg-blue-500/20 border border-blue-500/50 text-blue-300"
: "bg-neutral-700/30 text-neutral-500 hover:bg-neutral-700/50 hover:text-neutral-400 border border-transparent" : "bg-neutral-700/30 border border-transparent text-neutral-400 hover:bg-neutral-700/50 hover:text-neutral-300"
} }
`} `}
> >

2
src/lib/quickstart/__tests__/templates.test.ts

@ -104,7 +104,7 @@ describe("templates", () => {
it("should return only display properties", () => { it("should return only display properties", () => {
const presets = getAllPresets(); const presets = getAllPresets();
presets.forEach((preset) => { presets.forEach((preset) => {
expect(Object.keys(preset)).toEqual(["id", "name", "description", "icon"]); expect(Object.keys(preset)).toEqual(["id", "name", "description", "icon", "category", "tags"]);
}); });
}); });

2
src/types/quickstart.ts

@ -1,6 +1,6 @@
export type QuickstartView = "initial" | "templates" | "vibe"; export type QuickstartView = "initial" | "templates" | "vibe";
export type TemplateCategory = "product" | "style" | "composition" | "community"; export type TemplateCategory = "simple" | "advanced" | "community";
export interface TemplateMetadata { export interface TemplateMetadata {
nodeCount: number; nodeCount: number;

Loading…
Cancel
Save