Skip to content

Commit cab4ddd

Browse files
committed
feat: dual install methods in skills modal
1 parent a91630c commit cab4ddd

2 files changed

Lines changed: 86 additions & 22 deletions

File tree

app/components/PackageSkillsModal.vue

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ function toggleSkill(dirName: string) {
2727
expandedSkills.value = new Set(expandedSkills.value)
2828
}
2929
30-
const requestUrl = useRequestURL()
31-
const baseUrl = computed(() => `${requestUrl.protocol}//${requestUrl.host}`)
30+
type InstallMethod = 'skills-npm' | 'skills-cli'
31+
const selectedMethod = ref<InstallMethod>('skills-npm')
32+
33+
const baseUrl = computed(() =>
34+
typeof window !== 'undefined' ? window.location.origin : 'https://npmx.dev',
35+
)
3236
3337
const installCommand = computed(() => {
3438
if (!props.skills.length) return null
@@ -94,40 +98,99 @@ function handleKeydown(event: KeyboardEvent) {
9498
</button>
9599
</div>
96100

97-
<!-- Terminal-style install command -->
101+
<!-- Install header with tabs -->
102+
<div class="flex flex-wrap items-center justify-between gap-2 mb-3">
103+
<h3 class="text-xs text-fg-subtle uppercase tracking-wider">Install</h3>
104+
<div
105+
class="flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md"
106+
role="tablist"
107+
aria-label="Installation method"
108+
>
109+
<button
110+
role="tab"
111+
:aria-selected="selectedMethod === 'skills-npm'"
112+
:tabindex="selectedMethod === 'skills-npm' ? 0 : -1"
113+
type="button"
114+
class="px-2 py-1 font-mono text-xs rounded transition-colors duration-150 border border-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
115+
:class="
116+
selectedMethod === 'skills-npm'
117+
? 'bg-bg border-border shadow-sm text-fg'
118+
: 'border-transparent text-fg-subtle hover:text-fg'
119+
"
120+
@click="selectedMethod = 'skills-npm'"
121+
>
122+
skills-npm
123+
</button>
124+
<button
125+
role="tab"
126+
:aria-selected="selectedMethod === 'skills-cli'"
127+
:tabindex="selectedMethod === 'skills-cli' ? 0 : -1"
128+
type="button"
129+
class="px-2 py-1 font-mono text-xs rounded transition-colors duration-150 border border-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
130+
:class="
131+
selectedMethod === 'skills-cli'
132+
? 'bg-bg border-border shadow-sm text-fg'
133+
: 'border-transparent text-fg-subtle hover:text-fg'
134+
"
135+
@click="selectedMethod = 'skills-cli'"
136+
>
137+
skills CLI
138+
</button>
139+
</div>
140+
</div>
141+
142+
<!-- skills-npm: requires setup -->
143+
<div
144+
v-if="selectedMethod === 'skills-npm'"
145+
class="flex items-center justify-between gap-2 px-3 py-2.5 sm:px-4 bg-bg-subtle border border-border rounded-lg mb-5"
146+
>
147+
<span class="text-sm text-fg-muted"
148+
>Requires <code class="font-mono text-fg">skills-npm</code> setup</span
149+
>
150+
<a
151+
href="/skills-npm"
152+
class="inline-flex items-center gap-1 text-xs text-fg-subtle hover:text-fg transition-colors shrink-0"
153+
>
154+
Learn more
155+
<span class="i-carbon:arrow-right w-3 h-3" />
156+
</a>
157+
</div>
158+
159+
<!-- skills CLI: terminal command -->
98160
<div
99-
v-if="installCommand"
161+
v-else-if="installCommand"
100162
class="bg-bg-subtle border border-border rounded-lg overflow-hidden mb-5"
101163
>
102164
<div class="flex gap-1.5 px-3 pt-2 sm:px-4 sm:pt-3">
103-
<span class="size-2.5 rounded-full bg-fg-subtle/50" />
104-
<span class="size-2.5 rounded-full bg-fg-subtle/50" />
105-
<span class="size-2.5 rounded-full bg-fg-subtle/50" />
165+
<span class="w-2.5 h-2.5 rounded-full bg-fg-subtle" />
166+
<span class="w-2.5 h-2.5 rounded-full bg-fg-subtle" />
167+
<span class="w-2.5 h-2.5 rounded-full bg-fg-subtle" />
106168
</div>
107169
<div class="px-3 pt-2 pb-3 sm:px-4 sm:pt-3 sm:pb-4 overflow-x-auto">
108-
<div class="flex items-center gap-2">
170+
<div class="flex items-center gap-2 group/cmd">
109171
<span class="text-fg-subtle font-mono text-sm select-none shrink-0">$</span>
110-
<code class="font-mono text-sm text-fg-muted whitespace-nowrap">
111-
npx skills add {{ baseUrl }}/{{ packageName }}
112-
</code>
172+
<code class="font-mono text-sm"
173+
><span class="text-fg">npx </span
174+
><span class="text-fg-muted"
175+
>skills add {{ baseUrl }}/{{ packageName }}</span
176+
></code
177+
>
113178
<button
114179
type="button"
115-
class="p-1.5 text-fg-muted rounded transition-colors duration-200 hover:text-fg hover:bg-bg-muted active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 shrink-0"
180+
class="px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/cmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
116181
:aria-label="$t('package.get_started.copy_command')"
117182
@click.stop="copyCommand"
118183
>
119-
<span
120-
v-if="copied"
121-
class="i-carbon:checkmark size-4 block"
122-
aria-hidden="true"
123-
/>
124-
<span v-else class="i-carbon:copy size-4 block" aria-hidden="true" />
184+
<span aria-live="polite">{{
185+
copied ? $t('common.copied') : $t('common.copy')
186+
}}</span>
125187
</button>
126188
</div>
127189
</div>
128190
</div>
129191

130-
<!-- Skills list with expandable descriptions -->
192+
<!-- Skills list -->
193+
<h3 class="text-xs text-fg-subtle uppercase tracking-wider mb-2">Available Skills</h3>
131194
<ul class="space-y-0.5 list-none m-0 p-0">
132195
<li v-for="skill in skills" :key="skill.dirName">
133196
<button
@@ -137,14 +200,14 @@ function handleKeydown(event: KeyboardEvent) {
137200
@click="toggleSkill(skill.dirName)"
138201
>
139202
<span
140-
class="i-carbon:chevron-right w-3.5 h-3.5 text-fg-subtle shrink-0 transition-transform duration-200"
203+
class="i-carbon:chevron-right w-3 h-3 text-fg-subtle shrink-0 transition-transform duration-200"
141204
:class="{ 'rotate-90': expandedSkills.has(skill.dirName) }"
142205
aria-hidden="true"
143206
/>
144207
<span class="font-mono text-sm text-fg-muted">{{ skill.name }}</span>
145208
<span
146209
v-if="skill.warnings?.length"
147-
class="i-carbon:warning size-3.5 text-amber-500 shrink-0"
210+
class="i-carbon:warning w-3.5 h-3.5 text-amber-500 shrink-0"
148211
:title="getWarningTooltip(skill)"
149212
/>
150213
</button>

app/pages/[...package].vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,8 @@ function handleClick(event: MouseEvent) {
656656

657657
<!-- Stats grid -->
658658
<dl
659-
class="grid grid-cols-2 sm:grid-cols-12 gap-3 sm:gap-4 py-4 sm:py-6 mt-4 sm:mt-6 border-t border-border"
659+
class="grid grid-cols-2 gap-3 sm:gap-4 py-4 sm:py-6 mt-4 sm:mt-6 border-t border-border"
660+
:class="skillsData?.skills?.length ? 'sm:grid-cols-12' : 'sm:grid-cols-11'"
660661
>
661662
<div v-if="pkg.license" class="space-y-1 sm:col-span-2">
662663
<dt class="text-xs text-fg-subtle uppercase tracking-wider">

0 commit comments

Comments
 (0)