Skip to main content
Version: v1 (Current)

Quick Start

This guide walks you through building a simple form using UI Kit components.

Prerequisites

Complete the Installation guide first.

Basic Usage

Importing Components

Import components individually for tree-shaking:

import { Button, Input } from '@gxp-dev/uikit'

Simple Button

<script setup lang="ts">
import { Button } from '@gxp-dev/uikit'

const handleClick = () => {
console.log('Button clicked!')
}
</script>

<template>
<Button @click="handleClick">
Click Me
</Button>
</template>

Button Variants

The Button component supports multiple visual variants:

<template>
<div class="flex gap-4">
<Button variant="default">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
</template>

Button Sizes

<template>
<div class="flex items-center gap-4">
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon">
<IconPlus class="h-4 w-4" />
</Button>
</div>
</template>

Form Example

Basic Form

<script setup lang="ts">
import { ref } from 'vue'
import { Button, Input } from '@gxp-dev/uikit'

const email = ref('')
const password = ref('')

const handleSubmit = () => {
console.log('Submitted:', { email: email.value, password: password.value })
}
</script>

<template>
<form @submit.prevent="handleSubmit" class="space-y-4 max-w-sm">
<div class="space-y-2">
<label for="email" class="text-sm font-medium">
Email
</label>
<Input
id="email"
v-model="email"
type="email"
placeholder="you@example.com"
required
/>
</div>

<div class="space-y-2">
<label for="password" class="text-sm font-medium">
Password
</label>
<Input
id="password"
v-model="password"
type="password"
placeholder="Enter password"
required
/>
</div>

<Button type="submit" class="w-full">
Sign In
</Button>
</form>
</template>

Form with Validation States

<script setup lang="ts">
import { ref, computed } from 'vue'
import { Button, Input } from '@gxp-dev/uikit'

const email = ref('')
const isValid = computed(() => email.value.includes('@'))
const touched = ref(false)
</script>

<template>
<div class="space-y-2">
<Input
v-model="email"
type="email"
placeholder="Enter email"
:class="{ 'border-red-500': touched && !isValid }"
@blur="touched = true"
/>
<p v-if="touched && !isValid" class="text-sm text-red-500">
Please enter a valid email address
</p>
</div>
</template>

Styling Components

Using the class Prop

All components accept a class prop for custom styling:

<template>
<Button class="w-full rounded-full">
Full Width Rounded Button
</Button>
</template>

Using the cn() Utility

For conditional classes, use the included cn() utility:

<script setup lang="ts">
import { ref } from 'vue'
import { Button, cn } from '@gxp-dev/uikit'

const isLoading = ref(false)
</script>

<template>
<Button
:class="cn(
'transition-all',
isLoading && 'opacity-50 cursor-not-allowed'
)"
:disabled="isLoading"
>
{{ isLoading ? 'Loading...' : 'Submit' }}
</Button>
</template>

TypeScript Usage

Type-Safe Props

Components are fully typed:

<script setup lang="ts">
import { Button, type ButtonVariants } from '@gxp-dev/uikit'

// Type-safe variant prop
const variant: ButtonVariants['variant'] = 'secondary'
</script>

<template>
<Button :variant="variant">Typed Button</Button>
</template>

Component Events

<script setup lang="ts">
import { Input } from '@gxp-dev/uikit'

const handleUpdate = (value: string | number) => {
console.log('New value:', value)
}
</script>

<template>
<Input @update:modelValue="handleUpdate" />
</template>

Using with Icons

The UI Kit works well with icon libraries like Lucide:

npm install lucide-vue-next
<script setup lang="ts">
import { Button } from '@gxp-dev/uikit'
import { Mail, ArrowRight, Loader2 } from 'lucide-vue-next'
</script>

<template>
<div class="flex gap-4">
<!-- Icon on left -->
<Button>
<Mail class="mr-2 h-4 w-4" />
Email
</Button>

<!-- Icon on right -->
<Button>
Continue
<ArrowRight class="ml-2 h-4 w-4" />
</Button>

<!-- Loading state -->
<Button disabled>
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
Please wait
</Button>

<!-- Icon only -->
<Button size="icon" variant="outline">
<Mail class="h-4 w-4" />
</Button>
</div>
</template>

Complete Example

Here's a complete login card example:

<script setup lang="ts">
import { ref } from 'vue'
import { Button, Input } from '@gxp-dev/uikit'

const email = ref('')
const password = ref('')
const isLoading = ref(false)

const handleSubmit = async () => {
isLoading.value = true
try {
// Your authentication logic here
await new Promise(resolve => setTimeout(resolve, 1000))
console.log('Login successful')
} finally {
isLoading.value = false
}
}
</script>

<template>
<div class="min-h-screen flex items-center justify-center bg-background">
<div class="w-full max-w-md p-8 space-y-6 bg-card rounded-lg shadow-lg">
<div class="text-center">
<h1 class="text-2xl font-bold text-card-foreground">
Welcome Back
</h1>
<p class="text-muted-foreground">
Sign in to your account
</p>
</div>

<form @submit.prevent="handleSubmit" class="space-y-4">
<div class="space-y-2">
<label for="email" class="text-sm font-medium">
Email
</label>
<Input
id="email"
v-model="email"
type="email"
placeholder="you@example.com"
required
:disabled="isLoading"
/>
</div>

<div class="space-y-2">
<label for="password" class="text-sm font-medium">
Password
</label>
<Input
id="password"
v-model="password"
type="password"
placeholder="Enter password"
required
:disabled="isLoading"
/>
</div>

<Button
type="submit"
class="w-full"
:disabled="isLoading"
>
{{ isLoading ? 'Signing in...' : 'Sign In' }}
</Button>
</form>

<div class="text-center">
<Button variant="link">
Forgot password?
</Button>
</div>
</div>
</div>
</template>

Next Steps