From c208bc38c6d9dd6be1f227f41985514a519d4b67 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Wed, 7 Oct 2026 14:53:07 +1100 Subject: [PATCH 1/3] fix(registry): quiet the Skill page run and install rail The rail stacked a logo row, three heading styles, two divider rules, a separate copy button, and bordered behavior chips. Each action stays; the noise around them goes. --- .../registry/app/components/SkillDetail.vue | 40 ++-- .../app/components/_SkillCommandPanel.vue | 188 ++++++++---------- .../skill-detail-howto-schema.nuxt.test.ts | 7 +- 3 files changed, 112 insertions(+), 123 deletions(-) diff --git a/layers/registry/app/components/SkillDetail.vue b/layers/registry/app/components/SkillDetail.vue index 3d00f745..d492bc0f 100644 --- a/layers/registry/app/components/SkillDetail.vue +++ b/layers/registry/app/components/SkillDetail.vue @@ -1840,20 +1840,33 @@ useHead(computed(() => ({ class="hidden lg:block" aria-labelledby="rail-behaviors-heading" > -

- Skill behaviors -

+
+

+ Skill behaviors +

+ + Where each one appears + +
- - Where each one appears - diff --git a/layers/registry/app/components/_SkillCommandPanel.vue b/layers/registry/app/components/_SkillCommandPanel.vue index 7cd6f450..4fee26d3 100644 --- a/layers/registry/app/components/_SkillCommandPanel.vue +++ b/layers/registry/app/components/_SkillCommandPanel.vue @@ -2,7 +2,6 @@ import type { RunCheckFlag } from '#shared/run-check-flags' import type { ZipState } from '../utils/skill-zip' import { SKILL_RUN_PROMPT_LEAD } from '#shared/skill-commands' -import { AGENT_LOGOS } from '~/utils/agent-logos' import SkillRunFlag from './_SkillRunFlag.vue' type CommandMode = 'run' | 'install' @@ -59,7 +58,8 @@ const registrySetup: Record = { claude: { to: '/developers?setup=mcp&app=claude', label: 'Search the registry from Claude' }, chatgpt: { to: '/developers?setup=mcp&app=chatgpt', label: 'Search the registry from ChatGPT' }, } -const agentNames = AGENT_LOGOS.map(agent => agent.label).join(', ') +// A wrapped URL breaks after a path slash, never inside a name or the origin. +const runUrlParts = computed(() => runUrl.match(/^[a-z]+:\/\/[^/]+\/?|[^/]+\/|[^/]+$/gi) ?? [runUrl]) const mode = defineModel({ required: true }) @@ -74,6 +74,7 @@ const copyLabel = computed(() => commandCopied.value : mode.value === 'run' ? 'Copy Agent prompt' : 'Copy install command') const copyErrorId = useId() const installPanelId = useId() +const forkNoteId = useId() // Stacked shows both commands, so the copy error follows the last click. function copyFrom(next: CommandMode) { @@ -86,54 +87,31 @@ function copyFrom(next: CommandMode) {
-
- - -
- -
-
-

- Run once off -

-

- This session only. Nothing lands on disk. Nothing to clean up. -

-
-

- {{ SKILL_RUN_PROMPT_LEAD }} {{ runUrl }} +

+

+ Run once off +

+

+ Nothing lands on disk. Nothing to clean up.

- +
+ {{ `${SKILL_RUN_PROMPT_LEAD} ` }} + +
-
+

Install as a Skill

@@ -167,13 +145,13 @@ function copyFrom(next: CommandMode) {
+
+
+ +
    +
  • + + +

    + A fork creates an editable local Skill with its original author and licence. +

    +
  • +
  • + -
-
- -
- - Fork this Skill - -

- A fork creates an editable local Skill with its original author and licence. -

-
+ +

-
- -

- {{ SKILL_RUN_PROMPT_LEAD }} {{ runUrl }} -

- -
+ {{ `${SKILL_RUN_PROMPT_LEAD} ` }} + - This session only. Nothing lands on disk. + Nothing lands on disk. Nothing to clean up.

-
+
+ -

+

A fork creates an editable local Skill with its original author and licence.

@@ -327,24 +336,3 @@ function copyFrom(next: CommandMode) {

- - diff --git a/test/unit/skill-detail-howto-schema.nuxt.test.ts b/test/unit/skill-detail-howto-schema.nuxt.test.ts index 5e834d8f..32f196ca 100644 --- a/test/unit/skill-detail-howto-schema.nuxt.test.ts +++ b/test/unit/skill-detail-howto-schema.nuxt.test.ts @@ -203,8 +203,7 @@ describe('skillDetail command choice', () => { }) expect(tabs!.findAll('.install-command')).toHaveLength(1) - expect(tabs!.get('.install-command').text()).toBe('https://skilld.dev/gh/antfu/skills/vite') - expect(tabs!.text()).toContain('Use this Skill:') + expect(tabs!.get('.install-command').text()).toBe('Use this Skill: https://skilld.dev/gh/antfu/skills/vite') const installTab = tabs!.findAll('button[aria-pressed]').find(button => button.text() === 'Install') expect(installTab, 'Install mode is missing').toBeTruthy() await installTab!.trigger('click') @@ -213,10 +212,10 @@ describe('skillDetail command choice', () => { }) expect(stacked!.findAll('.install-command').map(command => command.text())).toEqual([ - 'https://skilld.dev/gh/antfu/skills/vite', + 'Use this Skill: https://skilld.dev/gh/antfu/skills/vite', 'npx skilld install antfu/skills/vite', ]) - expect(stacked!.findAll('button').some(button => button.text() === 'Copy prompt')).toBe(true) + expect(stacked!.get('button[aria-label="Copy Agent prompt"]')).toBeTruthy() expect(stacked!.get('button[aria-label="Copy install command"]')).toBeTruthy() wrapper.unmount() From acadebea7d1c98076ca281231344f8d094665dcf Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Wed, 7 Oct 2026 15:01:31 +1100 Subject: [PATCH 2/3] fix(registry): unbox the run flag and share the run prompt A third bordered box under the run command made the rail busy again whenever a run check failed. The run prompt markup was copied in both panel layouts; one component keeps their wrapping rules together. --- .../registry/app/components/SkillDetail.vue | 3 +- .../app/components/_SkillCommandPanel.vue | 35 ++++++++++--------- .../registry/app/components/_SkillRunFlag.vue | 6 ++-- .../app/components/_SkillRunPrompt.vue | 18 ++++++++++ 4 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 layers/registry/app/components/_SkillRunPrompt.vue diff --git a/layers/registry/app/components/SkillDetail.vue b/layers/registry/app/components/SkillDetail.vue index d492bc0f..1f434522 100644 --- a/layers/registry/app/components/SkillDetail.vue +++ b/layers/registry/app/components/SkillDetail.vue @@ -1807,7 +1807,7 @@ useHead(computed(() => ({
@@ -1867,6 +1867,7 @@ useHead(computed(() => ({ v-for="behavior in behaviors" :key="behavior.id" class="flex items-center gap-2" + :class="behavior.tier === 'ask' ? 'text-default' : undefined" > import type { RunCheckFlag } from '#shared/run-check-flags' import type { ZipState } from '../utils/skill-zip' -import { SKILL_RUN_PROMPT_LEAD } from '#shared/skill-commands' import SkillRunFlag from './_SkillRunFlag.vue' +import SkillRunPrompt from './_SkillRunPrompt.vue' type CommandMode = 'run' | 'install' type InstallTarget = 'local' | 'claude' | 'chatgpt' @@ -58,8 +58,6 @@ const registrySetup: Record = { claude: { to: '/developers?setup=mcp&app=claude', label: 'Search the registry from Claude' }, chatgpt: { to: '/developers?setup=mcp&app=chatgpt', label: 'Search the registry from ChatGPT' }, } -// A wrapped URL breaks after a path slash, never inside a name or the origin. -const runUrlParts = computed(() => runUrl.match(/^[a-z]+:\/\/[^/]+\/?|[^/]+\/|[^/]+$/gi) ?? [runUrl]) const mode = defineModel({ required: true }) @@ -90,17 +88,19 @@ function copyFrom(next: CommandMode) { class="space-y-8" >
-

- Run once off -

-

- Nothing lands on disk. Nothing to clean up. -

+
+

+ Run once off +

+

+ Nothing lands on disk. Nothing to clean up. +

+
- {{ `${SKILL_RUN_PROMPT_LEAD} ` }} +
- {{ `${SKILL_RUN_PROMPT_LEAD} ` }} +