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
96 changes: 96 additions & 0 deletions docs/.vitepress/theme/components/CopyPrompt.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script setup lang="ts">
import { Icon } from '@iconify/vue';
import { onBeforeUnmount, ref } from 'vue';

// Default getting-started prompt handed to an AI coding assistant. Every
// command and URL here is verified against the Getting Started guide and the
// live llms-full.txt docs dump.
const DEFAULT_PROMPT = `I want to use Vite+ in my project. Vite+ is the unified toolchain for the web behind the \`vp\` CLI — one tool combining Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task, plus runtime and package-manager management.

First, read https://viteplus.dev/llms-full.txt to learn Vite+'s commands and configuration.

Install the \`vp\` CLI:
- macOS / Linux: curl -fsSL https://vite.plus | bash
- Windows (PowerShell): irm https://vite.plus/ps1 | iex

Then open a new terminal and run \`vp help\`. To scaffold a new project run \`vp create\`; to move an existing Vite project onto Vite+ run \`vp migrate\`.

Day-to-day commands: \`vp install\` (dependencies), \`vp dev\` (dev server), \`vp check\` (format + lint + type-check), \`vp test\` (tests), and \`vp build\` (production build).

Help me get set up and explain anything I should know.`;

const props = withDefaults(
defineProps<{
prompt?: string;
label?: string;
}>(),
{
prompt: DEFAULT_PROMPT,
label: 'Copy Prompt',
},
);

const state = ref<'idle' | 'copied' | 'error'>('idle');
let resetTimer: ReturnType<typeof setTimeout> | null = null;

const flash = (next: 'copied' | 'error') => {
state.value = next;
if (resetTimer) {
clearTimeout(resetTimer);
}
resetTimer = setTimeout(() => {
state.value = 'idle';
resetTimer = null;
}, 1600);
};

const copyPrompt = async (event: MouseEvent) => {
// The theme draws the `.button` border with an `outline`, but a global reset
// (`button:focus:not(:focus-visible) { outline: none !important }`) strips it
// after a mouse click. The theme only ever uses `.button` on <a> tags, so this
// bites only real <button> elements. For pointer activation (event.detail > 0)
// drop focus so the button returns to its resting state and keeps its border;
// keyboard activation (detail === 0) keeps focus so the a11y focus ring shows.
if (event.detail > 0) {
(event.currentTarget as HTMLElement | null)?.blur();
}
try {
await navigator.clipboard.writeText(props.prompt);
flash('copied');
} catch {
flash('error');
}
};

onBeforeUnmount(() => {
if (resetTimer) {
clearTimeout(resetTimer);
}
});
</script>

<template>
<button
type="button"
class="button"
:aria-label="`${label} for setting up Vite+ with an AI assistant`"
@click="copyPrompt"
>
<Icon
:icon="
state === 'copied' ? 'lucide:check' : state === 'error' ? 'lucide:x' : 'lucide:clipboard'
"
class="size-4"
aria-hidden="true"
/>
<span>{{ state === 'copied' ? 'Copied!' : state === 'error' ? 'Could not copy' : label }}</span>
</button>
</template>

<style scoped>
.button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
</style>
3 changes: 2 additions & 1 deletion docs/.vitepress/theme/components/home/Hero.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</p>
<p class="text-sm text-grey">Free and open source under the MIT license.</p>
</div>
<div class="flex items-center gap-5">
<div class="flex flex-wrap items-center justify-center gap-5">
<a href="/guide" target="_self" class="button button--primary"> Get started </a>
<a
href="https://voidzero.dev/posts/announcing-vite-plus-alpha"
Expand All @@ -22,6 +22,7 @@
>
Read the Announcement
</a>
<CopyPrompt />
</div>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
import BaseTheme from '@voidzero-dev/vitepress-theme/src/viteplus';
import type { Theme } from 'vitepress';

import CopyPrompt from './components/CopyPrompt.vue';
import Layout from './Layout.vue';
import './styles.css';
import 'virtual:group-icons.css';

export default {
extends: BaseTheme,
Layout,
enhanceApp({ app }) {
// Globally available so Markdown pages can use <CopyPrompt /> without an import.
app.component('CopyPrompt', CopyPrompt);
},
} satisfies Theme;
4 changes: 4 additions & 0 deletions docs/guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Vite+ is the unified toolchain and entry point for web development. It manages y

Vite+ ships in two parts: `vp`, the global command-line tool, and `vite-plus`, the local package installed in each project. If you already have a Vite project, use [`vp migrate`](/guide/migrate) to migrate it to Vite+, or paste our [migration prompt](/guide/migrate#migration-prompt) into your coding agent.

Building with an AI assistant? Copy a ready-made setup prompt:

<CopyPrompt />

## Install `vp`

### macOS / Linux
Expand Down
Loading