Skip to content

jenxi/astro-wizard-forms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Astro Wizard Forms

A fully configurable, JSON-driven wizard form system for Astro with 10+ field types, comprehensive validation, and keyboard shortcuts.

Features

✨ JSON-Driven Configuration - No code changes needed to create or modify forms 🎯 10 Field Types - Single/multi-select, yes/no, text, email, phone, URL, number, name, textarea ⌨️ Keyboard Shortcuts - A-Z for options, Y/N for yes/no, Enter/Esc/Arrows for navigation βœ… Built-in Validation - Email, URL, phone, number validation out of the box 🎨 Customizable Styles - Theme via CSS variables or JSON configuration πŸ” Optional CAPTCHA - Support for Cloudflare Turnstile (reCAPTCHA coming soon) πŸ“± Responsive - Mobile-first design with touch-friendly interactions β™Ώ Accessible - Screen reader friendly, keyboard navigable

Installation

pnpm add astro-wizard-forms

Quick Start

1. Create your form configuration

Create a JSON file with your form structure:

{
  "metadata": {
    "title": "Contact Form",
    "submitButtonText": "Send Message"
  },
  "profileSelection": {
    "label": "How can we help?",
    "field": "profileType",
    "required": true,
    "options": [
      {
        "value": "support",
        "label": "Support",
        "description": "Get technical help"
      },
      {
        "value": "sales",
        "label": "Sales",
        "description": "Product inquiries"
      }
    ]
  },
  "branches": {
    "support": [
      {
        "field": "issue",
        "label": "What's the issue?",
        "type": "single-select",
        "required": true,
        "options": ["Bug", "Question", "Feature Request"]
      },
      {
        "field": "email",
        "label": "Your email?",
        "type": "email",
        "required": true
      }
    ]
  }
}

2. Use in your Astro page

---
import formConfig from './form-config.json';
---

<section id="contact-form" class="min-h-screen flex items-center justify-center">
  <div class="max-w-2xl w-full">
    <div id="form-container">
      <!-- Profile Selection -->
      <div id="profile-selection" class="space-y-4">
        <h2 class="text-3xl font-semibold">{formConfig.profileSelection.label}</h2>
        <div class="flex flex-col gap-4">
          {formConfig.profileSelection.options.map((option, index) => (
            <label class="profile-option cursor-pointer">
              <input
                type="radio"
                name="profileType"
                value={option.value}
                class="sr-only"
              />
              <div class="p-6 border rounded-lg">
                <span class="font-semibold">{option.label}</span>
                <p class="text-sm text-gray-600">{option.description}</p>
              </div>
            </label>
          ))}
        </div>
      </div>

      <!-- Dynamic Form (rendered by JS) -->
      <div id="branch-form" class="hidden"></div>
    </div>

    <!-- Confirmation -->
    <div id="confirmation" class="hidden"></div>
  </div>
</section>

<script>
  import { initWizardForm } from 'astro-wizard-forms';
  import formConfig from './form-config.json';

  async function handleSubmit(data, captchaToken) {
    const response = await fetch('/api/submit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...data, captchaToken })
    });

    const result = await response.json();
    return {
      success: response.ok,
      error: result.error
    };
  }

  initWizardForm({
    config: formConfig,
    onSubmit: handleSubmit,
    enableCaptcha: false, // Optional CAPTCHA
  });
</script>

3. Add CSS (optional, for default styling)

@import 'astro-wizard-forms/styles';

Or customize with your own styles using the provided CSS classes.

Field Types

Single Select (single-select)

Radio buttons with A-Z keyboard shortcuts.

{
  "field": "plan",
  "label": "Choose your plan",
  "type": "single-select",
  "required": true,
  "options": ["Free", "Pro", "Enterprise"]
}

Multi Select (multi-select)

Checkboxes allowing multiple selections.

{
  "field": "features",
  "label": "What features do you need?",
  "type": "multi-select",
  "required": true,
  "options": ["Analytics", "API Access", "Custom Domain"]
}

Yes/No (yes-no)

Binary choice with Y/N shortcuts.

{
  "field": "hasAccount",
  "label": "Do you have an account?",
  "type": "yes-no",
  "required": true
}

Text (text)

Single-line text input.

{
  "field": "company",
  "label": "Company name?",
  "type": "text",
  "required": true,
  "placeholder": "Acme Inc."
}

Multi-line Text (multi-line-text)

Textarea for longer input.

{
  "field": "message",
  "label": "Your message",
  "type": "multi-line-text",
  "required": true,
  "placeholder": "Tell us more..."
}

Name (name)

Automatic first/last name fields.

{
  "field": "name",
  "label": "What's your name?",
  "type": "name",
  "required": true
}

Email (email)

Email with validation.

{
  "field": "email",
  "label": "Your email?",
  "type": "email",
  "required": true,
  "placeholder": "you@example.com"
}

Phone (phone)

International phone format.

{
  "field": "phone",
  "label": "Phone number?",
  "type": "phone",
  "required": false,
  "placeholder": "+1 234 567 8900"
}

URL (url)

URL with http/https validation.

{
  "field": "website",
  "label": "Your website?",
  "type": "url",
  "required": false,
  "placeholder": "https://example.com"
}

Number (number)

Numeric input with min/max.

{
  "field": "age",
  "label": "Your age?",
  "type": "number",
  "required": true,
  "min": 18,
  "max": 120
}

Keyboard Shortcuts

  • A-Z - Select options (single/multi-select)
  • Y/N - Yes/No selection
  • Enter (↡) - Advance to next step
  • Escape (Esc) - Go back to previous step
  • Arrow Right (β†’) - Advance (if field filled)
  • Arrow Left (←) - Go back

CAPTCHA Integration

Cloudflare Turnstile

<script>
  initWizardForm({
    config: formConfig,
    onSubmit: handleSubmit,
    enableCaptcha: true,
    captchaProvider: 'turnstile',
    captchaSiteKey: 'your-site-key'
  });
</script>

Don't forget to add the Turnstile script to your layout:

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

Country Flags

Add country flags to select options:

initWizardForm({
  config: formConfig,
  onSubmit: handleSubmit,
  countryFlags: {
    'United States': 'πŸ‡ΊπŸ‡Έ',
    'Canada': 'πŸ‡¨πŸ‡¦',
    'United Kingdom': 'πŸ‡¬πŸ‡§'
  }
});

Customization

Via CSS Variables

:root {
  --wizard-bg: linear-gradient(45deg, #667eea, #764ba2);
  --wizard-option-bg: #1e1b4b;
  --wizard-option-selected: #312e81;
  --wizard-text: #ffffff;
}

Via JSON Configuration

{
  "styles": {
    "background": "#ffffff",
    "optionBackground": "#f3f4f6",
    "optionBackgroundSelected": "#3b82f6",
    "textColor": "#111827"
  }
}

API Reference

initWizardForm(options)

Options:

  • config (required): FormConfig object
  • onSubmit (required): Async function that handles form submission
  • enableCaptcha (optional): Enable CAPTCHA (default: false)
  • captchaProvider (optional): 'turnstile' | 'recaptcha' (default: 'turnstile')
  • captchaSiteKey (optional): CAPTCHA site key
  • countryFlags (optional): Record<string, string> - Country emoji mappings

Returns: void

Examples

See the /examples directory for complete working examples:

  • basic-form-config.json - Simple contact form
  • Advanced multi-branch form (coming soon)
  • Custom styled form (coming soon)

Requirements

  • Astro ^5.0.0
  • Modern browser with ES2022 support

License

MIT

Contributing

Contributions welcome! Please open an issue or PR.

Support

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors