Mimic a Desktop Window Using Vue
Tags: webdev, vue, javascript, tutorial
Published: 2023-07-19 04:13:04

I want to make a draggable Windows-type component in my app. So today we'll be doing just that with `v-drag`.


![Vue Desktop Window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/24pwug7ayesbrymg0vsf.gif)

## Step 1: Initialize a Vue app.

```sh
npm init vue@latest window-vue
cd window-vue
npm install
```
## Step 2: Install TailwindCSS, Font Awesome Icons, and v-drag!

We'll use Tailwind and FontAwesome to style our component.

```sh
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

Now go to your `tailwind.config.js` file and paste this.

```js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

Paste this into your `src/assets/main.css` file...

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
Then install Font Awesome Icons for beautiful logos...

```sh
npm i --save @fortawesome/fontawesome-svg-core
npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
npm i --save @fortawesome/free-brands-svg-icons
npm i --save @fortawesome/vue-fontawesome@latest-3
```

## Step 3: Install and use the last library `v-drag`.

```sh
npm install v-drag
```

Now that you have v-drag, let's set it up on our `src/main.js` or `src/main.ts`.*

> *Note: If you're using Typescript, add a `src/declarations.d.ts` file anywhere inside your `src/` folder.
> Inside your `src/declarations.d.ts`, add this bit `declare module "v-drag";`

```js
// ...
import App from './App.vue'
import router from './router'
import drag from "v-drag";

const app = createApp(App)
app.use(router)
app.use(drag)

app.mount('#app')
// ...
```

Step 4: Time to make something cool.

We'll only be using Font Awesome's `fa-circle` logo.

To make something draggable, we just use the `v-drag` directive to move it around.



```vue
<script setup lang="ts">
import { faCircle } from '@fortawesome/free-solid-svg-icons';
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
library.add(faCircle);
</script>

<template>
  <div v-drag>
    Hello! Drag me.
  </div>
</template>
```

![Using v-drag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7b0ebmg16txbajd0fra.gif)

Now that we know how to use v-drag, let's add in a few styling on our component!

```vue
<script lang="ts" setup>
// ...
const handleWindow = {
  handle: "#window-handle" // Will be the only element that can be clicked to drag the entire v-drag.
}
</script>

<template>
  <main class="bg-black w-screen h-screen relative text-gray-200 overflow-hidden">
    <div v-drag="handleWindow" class="bg-slate-950 max-w-2xl border rounded-lg absolute w-full -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2">
      <div class="flex border-b">
        <div class="flex items-center px-2 w-full" id="window-handle">
          <p>Window in Vue</p>
        </div>
        <div class="w-fit text-xs flex items-center justify-end px-2">
          <font-awesome-icon class="ml-2" icon="fa-solid fa-circle" />
          <font-awesome-icon class="ml-2" icon="fa-solid fa-circle" />
          <font-awesome-icon class="ml-2" icon="fa-solid fa-circle" />
        </div>
      </div>
      <div class="p-4">
        <h1 class="text-lg">Need Money</h1>
        <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Recusandae velit eaque, sunt temporibus expedita alias accusamus mollitia ut qui quasi cumque facere. Deserunt incidunt voluptate iste ex laudantium recusandae nostrum!</p>
      </div>
    </div>
  </main>
</template>
```

`v-drag` accepts an options object containing `handle` that will be used to point to an element that can be used to drag the entire element using `v-drag`.

![Vue Desktop Window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/24pwug7ayesbrymg0vsf.gif)

So I guess that's it!