Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,127 changes: 524 additions & 603 deletions src/web-ui/src/app/scenes/skills/SkillsScene.scss

Large diffs are not rendered by default.

681 changes: 388 additions & 293 deletions src/web-ui/src/app/scenes/skills/SkillsScene.tsx

Large diffs are not rendered by default.

53 changes: 21 additions & 32 deletions src/web-ui/src/app/scenes/skills/components/SkillCard.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@use '../../../../component-library/styles/tokens' as *;

/* ───────────────────────────────────────────────────
SkillCard — vertical card with glassmorphism effect
SkillCard — compact card for discover tab grid
DOM:
.skill-card
::before (decorative circle blur)
Expand All @@ -18,9 +18,10 @@
─────────────────────────────────────────────────── */

.skill-card {
width: 360px;
height: 200px;
border-radius: 15px;
width: 100%;
height: 100%;
min-height: 150px;
border-radius: 12px;
background: var(--element-bg-soft);
display: flex;
flex-direction: column;
Expand All @@ -33,31 +34,27 @@
transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
box-shadow 0.35s ease;

// Top gradient overlay - shows on hover, covers entire card except footer
// Top gradient overlay
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 40px;
bottom: 0;
background: var(--skill-card-gradient);
opacity: 0;
transition: opacity 0.35s ease;
pointer-events: none;
z-index: 0;
}

&--no-actions::before {
bottom: 0;
}

&:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.2);
transform: translateY(-3px) scale(1.01);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);

&::before {
opacity: 0.4;
opacity: 0.25;
}
}

Expand All @@ -71,8 +68,7 @@
display: flex;
align-items: flex-start;
justify-content: space-between;
padding: $size-gap-3;
padding-bottom: 0;
padding: 12px 12px 8px;
position: relative;
z-index: 1;
}
Expand All @@ -81,8 +77,8 @@
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
width: 30px;
height: 30px;
border-radius: 8px;
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(8px);
Expand All @@ -104,7 +100,7 @@
// ── Body ──
&__body {
flex: 1;
padding: $size-gap-2 $size-gap-3;
padding: 0 12px;
display: flex;
flex-direction: column;
gap: 4px;
Expand All @@ -116,12 +112,12 @@
&__title-row {
display: flex;
align-items: center;
gap: $size-gap-2;
gap: 8px;
min-width: 0;
}

&__name {
font-size: 0.92em;
font-size: 0.9em;
font-weight: $font-weight-semibold;
color: var(--color-text-primary);
line-height: $line-height-base;
Expand Down Expand Up @@ -165,10 +161,11 @@
display: flex;
align-items: center;
width: 100%;
border-radius: 0 0 15px 15px;
border-radius: 0 0 12px 12px;
overflow: hidden;
position: relative;
z-index: 1;
margin-top: auto;

// Bottom gradient blur background matching card color
&::after {
Expand All @@ -179,14 +176,14 @@
right: 0;
bottom: 0;
background: var(--skill-card-gradient);
opacity: 0.5;
opacity: 0.35;
transition: opacity 0.35s ease;
pointer-events: none;
}
}

&:hover &__footer::after {
opacity: 1;
opacity: 0.6;
}

&__actions {
Expand All @@ -202,7 +199,7 @@
display: inline-flex;
align-items: center;
justify-content: center;
height: 35px;
height: 32px;
padding: 0;
border: none;
background: rgba(255, 255, 255, 0.08);
Expand Down Expand Up @@ -244,14 +241,6 @@
}
}

// ── Responsive ──
@media (max-width: 720px) {
.skill-card {
width: 100%;
min-height: 180px;
}
}

// ── Animations ──
@keyframes skill-card-in {
from {
Expand Down
6 changes: 2 additions & 4 deletions src/web-ui/src/app/scenes/skills/components/SkillCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ const SkillCard: React.FC<SkillCardProps> = ({
const Icon = iconKind === 'market' ? Package : Puzzle;
const openDetails = () => onOpenDetails?.();

const hasActions = actions.length > 0;

return (
<div
className={['skill-card', !hasActions && 'skill-card--no-actions'].filter(Boolean).join(' ')}
className="skill-card"
style={{
'--card-index': index,
'--skill-card-gradient': getCardGradient(accentSeed ?? name),
Expand Down Expand Up @@ -91,7 +89,7 @@ const SkillCard: React.FC<SkillCardProps> = ({
</div>

{/* Footer: action buttons */}
{hasActions && (
{actions.length > 0 && (
<div className="skill-card__footer">
<div className="skill-card__actions" onClick={(e) => e.stopPropagation()}>
{actions.map((action) => (
Expand Down
18 changes: 15 additions & 3 deletions src/web-ui/src/app/scenes/skills/hooks/useInstalledSkills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,17 @@ export function useInstalledSkills({ searchQuery, activeFilter }: UseInstalledSk

const filteredSkills = useMemo(() => {
return skills.filter((skill) => {
const matchesFilter = activeFilter === 'all' || skill.level === activeFilter;
let matchesFilter = true;
if (activeFilter === 'user') {
matchesFilter = skill.level === 'user' && !skill.isBuiltin;
} else if (activeFilter === 'project') {
matchesFilter = skill.level === 'project' && !skill.isBuiltin;
} else if (activeFilter === 'builtin') {
matchesFilter = skill.isBuiltin;
} else if (activeFilter === 'suite') {
matchesFilter = false;
}

const matchesQuery = !normalizedQuery || [
skill.name,
skill.description,
Expand All @@ -180,8 +190,10 @@ export function useInstalledSkills({ searchQuery, activeFilter }: UseInstalledSk

const counts = useMemo(() => ({
all: skills.length,
user: skills.filter((skill) => skill.level === 'user').length,
project: skills.filter((skill) => skill.level === 'project').length,
builtin: skills.filter((skill) => skill.isBuiltin).length,
user: skills.filter((skill) => skill.level === 'user' && !skill.isBuiltin).length,
project: skills.filter((skill) => skill.level === 'project' && !skill.isBuiltin).length,
suite: 0,
}), [skills]);

return {
Expand Down
2 changes: 1 addition & 1 deletion src/web-ui/src/app/scenes/skills/skillsSceneStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { create } from 'zustand';

export type InstalledFilter = 'all' | 'user' | 'project';
export type InstalledFilter = 'all' | 'builtin' | 'user' | 'project' | 'suite';

interface SkillsSceneState {
searchDraft: string;
Expand Down
18 changes: 16 additions & 2 deletions src/web-ui/src/locales/en-US/scenes/skills.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@
},
"filters": {
"all": "All",
"builtin": "Built-in",
"user": "User",
"project": "Project"
"project": "Project",
"suite": "Suites"
},
"categories": {
"all": "All installed skills, including built-in, user-level, and project-level.",
"builtin": "Core skills shipped with the app. They cannot be deleted.",
"user": "User-level skills installed globally for your account.",
"project": "Project-level skills for the current workspace.",
"suite": "Curated skill bundles that package related skills together (coming soon)."
},
"section": {
"user": {
Expand All @@ -64,6 +73,7 @@
"noMatch": "No matching marketplace skills found",
"noSkills": "No marketplace skills available"
},
"resultsInfo": "{{count}} results for \"{{query}}\"",
"item": {
"sourceLabel": "Source: ",
"installs": "Installs: {{count}}",
Expand Down Expand Up @@ -98,7 +108,8 @@
"user": "User-level (Global)",
"project": "Project-level (Current Workspace)",
"projectDisabled": " - Need to open workspace first",
"currentWorkspace": "Current workspace: {{path}}"
"currentWorkspace": "Current workspace: {{path}}",
"selectedProjectPath": "Selected project path: {{path}}"
},
"path": {
"label": "Skill Folder Path",
Expand All @@ -123,6 +134,9 @@
"item": {
"user": "User",
"project": "Project",
"builtin": "Built-in",
"userInstalled": "Installed",
"detail": "Details",
"deleteTooltip": "Delete",
"pathLabel": "Path:",
"openPathInExplorer": "Open this folder in file explorer",
Expand Down
18 changes: 16 additions & 2 deletions src/web-ui/src/locales/zh-CN/scenes/skills.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@
},
"filters": {
"all": "全部",
"builtin": "内置",
"user": "用户级",
"project": "项目级"
"project": "项目级",
"suite": "套件"
},
"categories": {
"all": "查看所有已安装的技能,包含内置、用户和项目级。",
"builtin": "系统出厂自带的核心技能,不可删除。",
"user": "全局安装到当前账户的用户级技能。",
"project": "当前工作区下的项目级技能。",
"suite": "精选技能套件将多个相关技能打包提供(敬请期待)。"
},
"section": {
"user": {
Expand All @@ -64,6 +73,7 @@
"noMatch": "没有找到匹配的市场技能",
"noSkills": "暂时没有可展示的市场技能"
},
"resultsInfo": "关键词「{{query}}」共 {{count}} 条相关结果",
"item": {
"sourceLabel": "来源: ",
"installs": "安装量: {{count}}",
Expand Down Expand Up @@ -98,7 +108,8 @@
"user": "用户级(全局)",
"project": "项目级(当前工作空间)",
"projectDisabled": " - 需要先打开工作区",
"currentWorkspace": "当前工作区: {{path}}"
"currentWorkspace": "当前工作区: {{path}}",
"selectedProjectPath": "所选项目路径: {{path}}"
},
"path": {
"label": "技能文件夹路径",
Expand All @@ -123,6 +134,9 @@
"item": {
"user": "用户级",
"project": "项目级",
"builtin": "内置",
"userInstalled": "已安装",
"detail": "详情",
"deleteTooltip": "删除",
"pathLabel": "路径:",
"openPathInExplorer": "在资源管理器中打开此文件夹",
Expand Down
18 changes: 16 additions & 2 deletions src/web-ui/src/locales/zh-TW/scenes/skills.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@
},
"filters": {
"all": "全部",
"builtin": "內建",
"user": "用戶級",
"project": "項目級"
"project": "項目級",
"suite": "套件"
},
"categories": {
"all": "查看所有已安裝的技能,包含內建、用戶與項目級。",
"builtin": "系統出廠內建的核心技能,不可刪除。",
"user": "為目前帳戶全域安裝的用戶級技能。",
"project": "目前工作區底下的項目級技能。",
"suite": "精選技能套件將多個相關技能打包提供(敬請期待)。"
},
"section": {
"user": {
Expand All @@ -64,6 +73,7 @@
"noMatch": "沒有找到匹配的市場技能",
"noSkills": "暫時沒有可展示的市場技能"
},
"resultsInfo": "關鍵詞「{{query}}」共 {{count}} 筆相關結果",
"item": {
"sourceLabel": "來源: ",
"installs": "安裝量: {{count}}",
Expand Down Expand Up @@ -98,7 +108,8 @@
"user": "用戶級(全局)",
"project": "項目級(當前工作空間)",
"projectDisabled": " - 需要先打開工作區",
"currentWorkspace": "當前工作區: {{path}}"
"currentWorkspace": "當前工作區: {{path}}",
"selectedProjectPath": "所選項目路徑: {{path}}"
},
"path": {
"label": "技能文件夾路徑",
Expand All @@ -123,6 +134,9 @@
"item": {
"user": "用戶級",
"project": "項目級",
"builtin": "內建",
"userInstalled": "已安裝",
"detail": "詳情",
"deleteTooltip": "刪除",
"pathLabel": "路徑:",
"openPathInExplorer": "在資源管理器中打開此文件夾",
Expand Down
Loading