v0.1.6·Getting Started
Get Started with Claude
Step-by-step guide to generating UI Lab components with Claude

Getting Started with Claude

In this tutorial, you'll learn how to use Claude to generate production-ready UI Lab components. By the end, you'll be able to describe what you want and get working, beautiful component code.

What You'll Build

We'll create a simple contact form component that:

  • Has email and message fields
  • Submits the form
  • Shows validation errors
  • Works on mobile and desktop
  • Is fully accessible

And you'll have Claude generate the code for you.

Step 1: Set Up Your Project

First, make sure you have UI Lab components installed:

npm install ui-lab-components

Then, import the theme provider in your main application file:

import { ThemeProvider } from 'ui-lab-components'

export default function App() {
  return (
    <ThemeProvider>
      <YourApp />
    </ThemeProvider>
  )
}

Step 2: Know What Components Are Available

Before talking to Claude, it helps to know what components UI Lab provides. Here are the main ones for building forms:

  • Button – Call-to-action buttons with variants (primary, secondary, outline, ghost)
  • Input – Text input fields with error states
  • TextArea – Multi-line text input
  • Label – Form field labels
  • Form – Container for form fields
  • FormField – Individual form field with validation
  • Card – Container for grouping content

Step 3: Tell Claude About UI Lab

When prompting Claude, provide context about UI Lab. Here's what to include:

Option A: Simple Reference (Quick Start)

Give Claude this brief context:

I'm using UI Lab components from 'ui-lab-components'.
Available components include:
- Button (variants: primary, secondary, outline, ghost)
- Input (with error states)
- TextArea
- Label
- Form, FormField
- Card

All components support:
- Dark mode automatically
- Full accessibility
- TypeScript typing
- Responsive design via CSS classes

Option B: Detailed Reference (Better Results)

Include more detail about design patterns:

I'm using UI Lab components. Here's how they work:

## Button
- variant: "primary" | "secondary" | "outline" | "ghost"
- Semantic meaning: primary for main CTA, secondary for alternatives
- Always include accessible labels

## Form Components
Components compose like this:
<Form>
  <FormField>
    <Label>Field Label</Label>
    <Input type="email" />
  </FormField>
  <Button variant="primary">Submit</Button>
</Form>

## Design Guidelines
- Use primary variant for main actions
- Use semantic color tokens (via className: text-accent, bg-background, etc)
- Responsive: Use Flex/Grid with responsive props
- Accessibility: Always label form fields and buttons

## Available Design Classes
- Colors: text-accent, bg-background, text-foreground, etc.
- Spacing: p-sm, p-md, p-lg, gap-md, etc.
- Responsive: Use CSS media queries or flex/grid responsive props

Option C: Use MCP Server Integration (Best)

If you have the MCP server running, tell Claude:

I have the UI Lab MCP server enabled. You can:
1. Query available components
2. Check component APIs and variants
3. Access design guidelines
4. Get up-to-date documentation

Use these capabilities to generate the most accurate code.

Step 4: Write Your Prompt

Now ask Claude to generate your component. Here's a good prompt template:

Create a contact form component using UI Lab components that:

1. Has fields for:
   - Email (required, must be valid email format)
   - Message (required, min 10 characters)

2. Features:
   - Submit button that says "Send Message"
   - Shows error messages below each field
   - Disables submit button while loading
   - Shows success message after submission
   - Responsive design that works on mobile

3. Style guide:
   - Use primary button for submit
   - Show errors in red (danger color)
   - Add proper spacing between fields
   - Support both light and dark modes

4. Accessibility:
   - All fields are properly labeled
   - Errors are announced to screen readers
   - Button shows loading state visually and with aria-busy

Generate the complete React component with TypeScript types.

Step 5: Review the Generated Code

Claude will generate something like this:

import React, { useState } from 'react'
import { Form, FormField, Label, Input, TextArea, Button, Card } from 'ui-lab-components'

interface ContactFormProps {
  onSuccess?: () => void
}

interface FormErrors {
  email?: string
  message?: string
}

export function ContactForm({ onSuccess }: ContactFormProps) {
  const [formData, setFormData] = useState({ email: '', message: '' })
  const [errors, setErrors] = useState<FormErrors>({})
  const [isLoading, setIsLoading] = useState(false)
  const [showSuccess, setShowSuccess] = useState(false)

  const validateForm = () => {
    const newErrors: FormErrors = {}

    if (!formData.email) {
      newErrors.email = 'Email is required'
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
      newErrors.email = 'Invalid email address'
    }

    if (!formData.message) {
      newErrors.message = 'Message is required'
    } else if (formData.message.length < 10) {
      newErrors.message = 'Message must be at least 10 characters'
    }

    return newErrors
  }

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    const newErrors = validateForm()

    if (Object.keys(newErrors).length > 0) {
      setErrors(newErrors)
      return
    }

    setIsLoading(true)
    try {
      // Your API call here
      await new Promise(resolve => setTimeout(resolve, 1000))
      setShowSuccess(true)
      setFormData({ email: '', message: '' })
      onSuccess?.()
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <Card className="w-full max-w-md mx-auto p-lg">
      <h2 className="text-lg font-semibold mb-md">Contact Us</h2>

      {showSuccess && (
        <div className="mb-md p-md bg-success-100 text-success-900 rounded">
          Message sent successfully!
        </div>
      )}

      <Form onSubmit={handleSubmit}>
        <FormField>
          <Label htmlFor="email">Email</Label>
          <Input
            id="email"
            type="email"
            value={formData.email}
            onChange={(e) => setFormData({ ...formData, email: e.target.value })}
            aria-invalid={!!errors.email}
            aria-describedby={errors.email ? 'email-error' : undefined}
          />
          {errors.email && (
            <div id="email-error" className="text-danger-600 text-sm mt-xs">
              {errors.email}
            </div>
          )}
        </FormField>

        <FormField>
          <Label htmlFor="message">Message</Label>
          <TextArea
            id="message"
            value={formData.message}
            onChange={(e) => setFormData({ ...formData, message: e.target.value })}
            aria-invalid={!!errors.message}
            aria-describedby={errors.message ? 'message-error' : undefined}
          />
          {errors.message && (
            <div id="message-error" className="text-danger-600 text-sm mt-xs">
              {errors.message}
            </div>
          )}
        </FormField>

        <Button
          variant="primary"
          type="submit"
          disabled={isLoading}
          aria-busy={isLoading}
          className="w-full"
        >
          {isLoading ? 'Sending...' : 'Send Message'}
        </Button>
      </Form>
    </Card>
  )
}

Perfect! This is production-ready code that:

  • ✅ Is fully typed with TypeScript
  • ✅ Includes proper accessibility
  • ✅ Follows UI Lab patterns
  • ✅ Handles errors gracefully
  • ✅ Works on all screen sizes
  • ✅ Supports dark mode automatically

Step 6: Customize if Needed

Claude may have generated more or less than you need. Common customizations:

Add a success state

Ask: "Add a success page that shows after submission with a 'Send Another' button"

Change the styling

Ask: "Make the form wider on desktop (max-w-2xl) and add a gradient background"

Add more fields

Ask: "Add a phone number field that's optional but validated if provided"

Integrate with an API

Ask: "Replace the setTimeout with a real API call to POST /api/contact"

Common Prompting Patterns

Pattern 1: Feature Request

Add [feature] to the component. It should [behavior].

Pattern 2: Styling Request

Style the component with [design description].
Use [specific colors/spacing/layout].

Pattern 3: Composition Request

Create a component that uses [other components] to build [desired result].

Pattern 4: Accessibility Fix

Improve the accessibility by [description].
Ensure it works with [screen readers/keyboard navigation].

Tips for Better Results

  1. Be Specific – Instead of "make it look better," say "use a card layout with rounded corners and a subtle shadow"

  2. Reference Components – Mention specific UI Lab components you want used: "use a Grid with 2 columns"

  3. Show Examples – If you have existing components, show them to Claude: "make it look like this [example code]"

  4. Use TypeScript – Ask for typed code: "Generate with full TypeScript types"

  5. Request Testing Code – Ask Claude to include test examples: "Add usage examples showing how to use this component"

  6. Mention Constraints – Tell Claude about limitations: "Keep the bundle size small," "use only CSS, no CSS-in-JS"

What's Next

Now that you know how to generate components with Claude:

Troubleshooting

Claude generates invalid prop names

Solution: Ensure Claude knows the exact prop names. Give it the component documentation or MCP access.

Generated code doesn't compile

Solution: Ask Claude to check TypeScript types. Share the error message: "I got this error: [error]. Please fix it."

Styling doesn't match your design

Solution: Provide more detail about the design. Include color tokens and spacing values from your theme.

Accessibility issues

Solution: Ask Claude to add specific accessibility features: "Add aria-labels for icon buttons"


You're now ready to generate beautiful UI Lab components with Claude. Happy coding!

© 2025 UI Lab • Built for humans and machines