From a91d709aa5939bb3c591ef059b01b2ccdea82f8c Mon Sep 17 00:00:00 2001 From: yyh Date: Fri, 23 Jan 2026 14:39:36 +0800 Subject: [PATCH] feat(skill-editor): add CategoryTabs and TemplateSearch to skill templates section Add filter controls for skill templates: - CategoryTabs: tab navigation with mock categories (All, Productivity, etc.) - TemplateSearch: search input with accessibility attributes - Grid layout fix to prevent tab width changes on font-weight switch Update SectionHeader to accept className prop for flexible styling. Add search placeholder i18n translations. --- .../skill/start-tab/category-tabs/index.tsx | 46 ++++++++++++++++++ .../start-tab/category-tabs/tab-item.tsx | 47 +++++++++++++++++++ .../skill/start-tab/section-header.tsx | 6 ++- .../start-tab/skill-templates-section.tsx | 18 ++++++- .../skill/start-tab/template-search.tsx | 35 ++++++++++++++ web/i18n/en-US/workflow.json | 1 + web/i18n/zh-Hans/workflow.json | 1 + 7 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 web/app/components/workflow/skill/start-tab/category-tabs/index.tsx create mode 100644 web/app/components/workflow/skill/start-tab/category-tabs/tab-item.tsx create mode 100644 web/app/components/workflow/skill/start-tab/template-search.tsx diff --git a/web/app/components/workflow/skill/start-tab/category-tabs/index.tsx b/web/app/components/workflow/skill/start-tab/category-tabs/index.tsx new file mode 100644 index 0000000000..723e7e6564 --- /dev/null +++ b/web/app/components/workflow/skill/start-tab/category-tabs/index.tsx @@ -0,0 +1,46 @@ +'use client' + +import type { FC } from 'react' +import { memo } from 'react' +import TabItem from './tab-item' + +export type TemplateCategory = { + id: string + label: string +} +// TODO: use real categories from backend +const MOCK_CATEGORIES: TemplateCategory[] = [ + { id: 'all', label: 'All' }, + { id: 'productivity', label: 'Productivity' }, + { id: 'analysis', label: 'Analysis' }, + { id: 'search', label: 'Search' }, + { id: 'development', label: 'Development' }, + { id: 'security', label: 'Security' }, +] + +type CategoryTabsProps = { + categories?: TemplateCategory[] + activeCategory: string + onCategoryChange: (categoryId: string) => void +} + +const CategoryTabs: FC = ({ + categories = MOCK_CATEGORIES, + activeCategory, + onCategoryChange, +}) => { + return ( +
+ {categories.map(category => ( + onCategoryChange(category.id)} + /> + ))} +
+ ) +} + +export default memo(CategoryTabs) diff --git a/web/app/components/workflow/skill/start-tab/category-tabs/tab-item.tsx b/web/app/components/workflow/skill/start-tab/category-tabs/tab-item.tsx new file mode 100644 index 0000000000..7d85ff780a --- /dev/null +++ b/web/app/components/workflow/skill/start-tab/category-tabs/tab-item.tsx @@ -0,0 +1,47 @@ +'use client' + +import type { FC } from 'react' +import { memo } from 'react' +import { cn } from '@/utils/classnames' + +type TabItemProps = { + label: string + isActive: boolean + onClick: () => void +} + +const TabItem: FC = ({ + label, + isActive, + onClick, +}) => { + return ( + + ) +} + +export default memo(TabItem) diff --git a/web/app/components/workflow/skill/start-tab/section-header.tsx b/web/app/components/workflow/skill/start-tab/section-header.tsx index 654da5127c..a9b369574c 100644 --- a/web/app/components/workflow/skill/start-tab/section-header.tsx +++ b/web/app/components/workflow/skill/start-tab/section-header.tsx @@ -6,18 +6,20 @@ import { memo } from 'react' type SectionHeaderProps = { title: string description: string + className?: string } const SectionHeader: FC = ({ title, description, + className, }) => { return ( -
+

{title}

-

+

{description}

diff --git a/web/app/components/workflow/skill/start-tab/skill-templates-section.tsx b/web/app/components/workflow/skill/start-tab/skill-templates-section.tsx index e306581fb3..1280ec4980 100644 --- a/web/app/components/workflow/skill/start-tab/skill-templates-section.tsx +++ b/web/app/components/workflow/skill/start-tab/skill-templates-section.tsx @@ -1,19 +1,33 @@ 'use client' import type { FC } from 'react' -import { memo } from 'react' +import { memo, useState } from 'react' import { useTranslation } from 'react-i18next' +import CategoryTabs from './category-tabs' import SectionHeader from './section-header' +import TemplateSearch from './template-search' const SkillTemplatesSection: FC = () => { const { t } = useTranslation('workflow') + const [activeCategory, setActiveCategory] = useState('all') + const [searchValue, setSearchValue] = useState('') return ( -
+
+
+ + +
{t('skill.startTab.templatesComingSoon')} diff --git a/web/app/components/workflow/skill/start-tab/template-search.tsx b/web/app/components/workflow/skill/start-tab/template-search.tsx new file mode 100644 index 0000000000..5a1677263d --- /dev/null +++ b/web/app/components/workflow/skill/start-tab/template-search.tsx @@ -0,0 +1,35 @@ +'use client' + +import type { FC } from 'react' +import { RiSearchLine } from '@remixicon/react' +import { memo } from 'react' +import { useTranslation } from 'react-i18next' + +type TemplateSearchProps = { + value: string + onChange: (value: string) => void +} + +const TemplateSearch: FC = ({ + value, + onChange, +}) => { + const { t } = useTranslation('workflow') + + return ( +
+
+ ) +} + +export default memo(TemplateSearch) diff --git a/web/i18n/en-US/workflow.json b/web/i18n/en-US/workflow.json index 09bf1b81d9..b0c97bb3e3 100644 --- a/web/i18n/en-US/workflow.json +++ b/web/i18n/en-US/workflow.json @@ -1035,6 +1035,7 @@ "skill.startTab.createBlankSkillDesc": "Start with an empty folder structure", "skill.startTab.importSkill": "Import Skill", "skill.startTab.importSkillDesc": "Import skill from skill.zip file", + "skill.startTab.searchPlaceholder": "Search…", "skill.startTab.templatesComingSoon": "Templates coming soon…", "skill.startTab.templatesDesc": "Choose a template to bootstrap your agent's capabilities", "skill.startTab.templatesTitle": "Skill Templates", diff --git a/web/i18n/zh-Hans/workflow.json b/web/i18n/zh-Hans/workflow.json index 82e9fa6a42..dccace9cb6 100644 --- a/web/i18n/zh-Hans/workflow.json +++ b/web/i18n/zh-Hans/workflow.json @@ -1027,6 +1027,7 @@ "skill.startTab.createBlankSkillDesc": "从空文件夹结构开始", "skill.startTab.importSkill": "导入 Skill", "skill.startTab.importSkillDesc": "从 skill.zip 文件导入", + "skill.startTab.searchPlaceholder": "搜索…", "skill.startTab.templatesComingSoon": "模板即将推出…", "skill.startTab.templatesDesc": "选择模板来快速构建你的 Agent 能力", "skill.startTab.templatesTitle": "Skill 模板",