feat(skill-editor): implement StartTabContent with modular component structure

Refactor StartTabContent into separate components following Figma design specs:
- ActionCard: reusable card with icon, title, description
- SectionHeader: title/xl-semi-bold header with description
- CreateImportSection: 3-column grid layout for Create/Import cards
- SkillTemplatesSection: templates area with placeholder

Align styles with Figma: 3-col grid, 16px title, proper spacing and padding.
Add i18n translations for all user-facing text (en-US, zh-Hans).
This commit is contained in:
yyh
2026-01-23 14:22:58 +08:00
parent 083f45678d
commit 4d465d6cf9
9 changed files with 162 additions and 24 deletions

View File

@ -20,7 +20,7 @@ import { useFileTypeInfo } from './hooks/use-file-type-info'
import { useSkillAssetNodeMap } from './hooks/use-skill-asset-tree'
import { useSkillFileData } from './hooks/use-skill-file-data'
import { useSkillFileSave } from './hooks/use-skill-file-save'
import StartTabContent from './start-tab-content'
import StartTabContent from './start-tab'
import { getFileLanguage } from './utils/file-utils'
import MediaFilePreview from './viewer/media-file-preview'
import UnsupportedFileDownload from './viewer/unsupported-file-download'

View File

@ -1,23 +0,0 @@
'use client'
import type { FC } from 'react'
import * as React from 'react'
import Home from '@/app/components/base/icons/src/vender/workflow/Home'
// TODO: use translations
const StartTabContent: FC = () => {
return (
<div className="flex h-full w-full flex-col items-center justify-center bg-components-panel-bg">
<div className="flex flex-col items-center gap-3">
<div className="flex size-12 items-center justify-center rounded-xl bg-components-panel-bg-blur">
<Home className="size-6 text-text-tertiary" />
</div>
<span className="system-sm-regular text-text-tertiary">
Coming soon...
</span>
</div>
</div>
)
}
export default React.memo(StartTabContent)

View File

@ -0,0 +1,49 @@
'use client'
import type { FC, ReactNode } from 'react'
import { memo } from 'react'
import { cn } from '@/utils/classnames'
type ActionCardProps = {
icon: ReactNode
title: string
description: string
onClick?: () => void
}
const ActionCard: FC<ActionCardProps> = ({
icon,
title,
description,
onClick,
}) => {
return (
<button
type="button"
className={cn(
'flex items-start gap-3 rounded-xl border border-components-panel-border-subtle bg-components-panel-on-panel-item-bg p-4',
'hover:bg-components-panel-on-panel-item-bg-hover',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-components-input-border-active',
'text-left transition-colors',
)}
onClick={onClick}
>
<div
className="flex size-10 shrink-0 items-center justify-center rounded-[10px] border border-dashed border-divider-regular bg-background-section"
aria-hidden="true"
>
{icon}
</div>
<div className="flex min-w-0 flex-1 flex-col gap-0.5 py-px">
<span className="system-md-semibold truncate text-text-secondary">
{title}
</span>
<span className="system-xs-regular text-text-tertiary">
{description}
</span>
</div>
</button>
)
}
export default memo(ActionCard)

View File

@ -0,0 +1,28 @@
'use client'
import type { FC } from 'react'
import { RiAddCircleFill, RiUploadLine } from '@remixicon/react'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import ActionCard from './action-card'
const CreateImportSection: FC = () => {
const { t } = useTranslation('workflow')
return (
<div className="grid grid-cols-3 gap-2 px-6 pb-4 pt-6">
<ActionCard
icon={<RiAddCircleFill className="size-5 text-text-accent" />}
title={t('skill.startTab.createBlankSkill')}
description={t('skill.startTab.createBlankSkillDesc')}
/>
<ActionCard
icon={<RiUploadLine className="size-5 text-text-accent" />}
title={t('skill.startTab.importSkill')}
description={t('skill.startTab.importSkillDesc')}
/>
</div>
)
}
export default memo(CreateImportSection)

View File

@ -0,0 +1,17 @@
'use client'
import type { FC } from 'react'
import { memo } from 'react'
import CreateImportSection from './create-import-section'
import SkillTemplatesSection from './skill-templates-section'
const StartTabContent: FC = () => {
return (
<div className="h-full w-full overflow-auto bg-components-panel-bg">
<CreateImportSection />
<SkillTemplatesSection />
</div>
)
}
export default memo(StartTabContent)

View File

@ -0,0 +1,27 @@
'use client'
import type { FC } from 'react'
import { memo } from 'react'
type SectionHeaderProps = {
title: string
description: string
}
const SectionHeader: FC<SectionHeaderProps> = ({
title,
description,
}) => {
return (
<header className="mb-3 flex flex-col gap-0.5">
<h2 className="title-xl-semi-bold text-text-primary">
{title}
</h2>
<p className="system-xs-regular text-text-tertiary">
{description}
</p>
</header>
)
}
export default memo(SectionHeader)

View File

@ -0,0 +1,26 @@
'use client'
import type { FC } from 'react'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import SectionHeader from './section-header'
const SkillTemplatesSection: FC = () => {
const { t } = useTranslation('workflow')
return (
<section className="px-6">
<SectionHeader
title={t('skill.startTab.templatesTitle')}
description={t('skill.startTab.templatesDesc')}
/>
<div className="flex min-h-[200px] items-center justify-center rounded-xl border border-dashed border-divider-regular bg-background-section-burn">
<span className="system-sm-regular text-text-quaternary">
{t('skill.startTab.templatesComingSoon')}
</span>
</div>
</section>
)
}
export default memo(SkillTemplatesSection)

View File

@ -1031,6 +1031,13 @@
"singleRun.testRun": "Test Run",
"singleRun.testRunIteration": "Test Run Iteration",
"singleRun.testRunLoop": "Test Run Loop",
"skill.startTab.createBlankSkill": "Create Blank Skill",
"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.templatesComingSoon": "Templates coming soon…",
"skill.startTab.templatesDesc": "Choose a template to bootstrap your agent's capabilities",
"skill.startTab.templatesTitle": "Skill Templates",
"skillEditor.authorizationRequired": "Authorization required before use.",
"skillEditor.previewUnavailable": "Preview unavailable",
"skillEditor.referenceFiles": "Reference files",

View File

@ -1023,6 +1023,13 @@
"singleRun.testRun": "测试运行",
"singleRun.testRunIteration": "测试运行迭代",
"singleRun.testRunLoop": "测试运行循环",
"skill.startTab.createBlankSkill": "创建空白 Skill",
"skill.startTab.createBlankSkillDesc": "从空文件夹结构开始",
"skill.startTab.importSkill": "导入 Skill",
"skill.startTab.importSkillDesc": "从 skill.zip 文件导入",
"skill.startTab.templatesComingSoon": "模板即将推出…",
"skill.startTab.templatesDesc": "选择模板来快速构建你的 Agent 能力",
"skill.startTab.templatesTitle": "Skill 模板",
"skillEditor.authorizationRequired": "使用前需要授权。",
"skillEditor.previewUnavailable": "无法预览",
"skillEditor.referenceFiles": "引用文件",