Skip to content

cwandel-afk/nuxdy-forms

Repository files navigation

Nuxdy Forms

npm version npm downloads License: MIT

An extremely lightweight dynamic form component library for Nuxt 3 applications. This library allows you to create highly configurable forms with various field types, nested fields, conditional rendering, and validation.

Features

  • Multiple Field Types: Support for text, email, number, textarea, select, radio, checkbox, checkbox groups, and more
  • Nested Fields: Create complex forms with nested field groups
  • Conditional Rendering: Show/hide fields based on the values of other fields
  • Validation: Built-in validation with customizable error messages
  • Styling: Highly configurable with Tailwind CSS classes
  • Callback Support: Submit form data to your backend API with a simple callback function
  • Nuxt UI Integration: Easily integrate with Nuxt UI components

Installation

# npm
npm install nuxdy-forms

# yarn
yarn add nuxdy-forms

# pnpm
pnpm add nuxdy-forms

Setup

Add the module to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: ["nuxdy-forms"],
  nuxdyForm: {
    useNuxtUI: true, // Enable Nuxt UI integration
  },
});

Nuxt UI Integration

Nuxdy Forms can be integrated with Nuxt UI to provide a consistent design system and additional UI components. To enable this integration:

  1. Install Nuxt UI in your project:
npm install @nuxt/ui
  1. Enable the integration in your nuxt.config.ts:
export default defineNuxtConfig({
  modules: ["nuxdy-forms"],
  nuxdyForm: {
    useNuxtUI: true,
  },
});

When Nuxt UI integration is enabled, Nuxdy Forms will:

  • Use Nuxt UI's design system and components
  • Provide better integration with Nuxt UI's form components
  • Maintain consistent styling with your Nuxt UI theme

Basic Usage

<template>
  <!-- Nuxdy Forms -->
  <NuxdyForm :config="formConfig" :submitCallback="handleSubmit" />

  <!-- Nuxt UI Integration -->
  <NuxdyUForm
    :config="formConfig"
    space-between-fields="2rem"
    @submit="handleSubmit"
  />
</template>
const formConfig = {
  id: "contact-form",
  title: "Contact Us",
  description: "Please fill out the form below to get in touch with us.",
  fields: [
    {
      id: "name",
      type: "text",
      label: "Full Name",
      required: true,
      placeholder: "Enter your full name",
    },
    {
      id: "email",
      type: "email",
      label: "Email Address",
      required: true,
      placeholder: "your.email@example.com",
      validation: {
        message: "Please enter a valid email address",
      },
    },
    {
      id: "message",
      type: "textarea",
      label: "Message",
      required: true,
      rows: 4,
      placeholder: "How can we help you?",
    },
  ],
  submitLabel: "Send Message",
  resetLabel: "Clear Form",
};

const handleSubmit = async (formData) => {
  // Handle form submission
};

Form Configuration

The form configuration object has the following structure:

interface FormConfig {
  id: string;
  title?: string;
  description?: string;
  fields: FormField[];
  submitLabel?: string;
  resetLabel?: string;
  buttonPlacement?: "left" | "right"; // Currently only supported in Nuxt UI Integration
}

Field Types

Nuxt UI Specific properties (Apply for all fields)

  • description: Description for the field
  • hint: Hint for the field
  • error: Error message for the field
  • size: Size for the field
  • width: Width for the field

Text, Email, Number

{
  id: "fieldId",
  type: "text", // or "email" or "number"
  label: "Field Label",
  placeholder: "Placeholder text",
  required: true,
  helpText: "Help text for the field",
  min: 0,
  max: 100,
  validation: {
    rules: ["required", "email"], // Built-in validation rules
    message: "Custom error message"
  },
  defaultValue: "Default value",
}

Textarea

{
  id: "message",
  type: "textarea",
  label: "Message",
  placeholder: "Enter your message",
  rows: 4,
  required: true
}

Select, Radio, Checkbox Group

{
  id: "category",
  type: "select", // or "radio" or "checkbox-group"
  label: "Category",
  options: [
    { value: "option1", label: "Option 1" },
    { value: "option2", label: "Option 2" },
    { value: "option3", label: "Option 3" }
  ],
  required: true,
  defaultValue: "option1" // For select/radio
  // For checkbox-group, defaultValue would be an array: ["option1", "option2"]
}

Checkbox

{
  id: "subscribe",
  type: "checkbox",
  label: "Subscribe to newsletter",
  defaultValue: false
}

Group (Nested Fields)

{
  id: "address",
  type: "group",
  label: "Address",
  fields: [
    {
      id: "street",
      type: "text",
      label: "Street",
      required: true
    },
    {
      id: "city",
      type: "text",
      label: "City",
      required: true
    },
    {
      id: "zipCode",
      type: "text",
      label: "ZIP Code",
      required: true
    }
  ]
}

List (Array of Objects)

{
  id: "contacts",
  type: "list",
  label: "Additional Contacts",
  fields: [
    {
      id: "name",
      type: "text",
      label: "Name",
      required: true
    },
    {
      id: "email",
      type: "email",
      label: "Email",
      required: true
    }
  ],
  addButtonLabel: "Add Contact",
  removeButtonLabel: "Remove",
  minItems: 0,
  maxItems: 5
}

Conditional Fields

You can show/hide fields based on the values of other fields:

{
  id: "hasChildren",
  type: "checkbox",
  label: "Do you have children?",
  defaultValue: false
},
{
  id: "numberOfChildren",
  type: "number",
  label: "Number of children",
  min: 1,
  conditions: [
    {
      field: "hasChildren",
      operator: "==",
      value: true
    }
  ]
}

Styling

You can customize the appearance of the form by overriding the default classes (You can use tailwind or css to override the styles):

/* Base form styles */
.nuxdy-form {
  width: 100%;
  margin-bottom: 1.5rem;
  padding: 1.5rem;
  border-radius: 0.5rem;
}

.nuxdy-form-field {
  width: 100%;
  height: 100%;
  margin-bottom: 1rem;
}

.nuxdy-form-label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  color: #374151;
  margin-bottom: 0.25rem;
}

/* ----------------------------------------------------------- */

.nuxdy-form-field-label {
  font-size: 0.875rem;
  font-weight: 500;
}

/* ----------------------------------------------------------- */

.nuxdy-form-input {
  width: 100%;
  min-height: 3rem;
  padding: 1rem;
  border-radius: 0.5rem;
  border: 0.15rem solid lightgrey;
  outline: none;
  font-size: 0.875rem;
  box-shadow: 0px 0px 20px -18px;
}

.nuxdy-form-input:hover {
  border: 2px solid lightgrey;
  box-shadow: 0px 0px 20px -17px;
}

.nuxdy-form-input:focus {
  border: 2px solid grey;
}

/* ----------------------------------------------------------- */

.nuxdy-form-select {
  width: 100%;
  min-height: 3rem;
  padding-inline: 1rem;
  border-radius: 0.5rem;
  border: 0.15rem solid lightgrey;
  outline: none;
  font-size: 0.875rem;
  box-shadow: 0px 0px 20px -18px;
}

.nuxdy-form-select:hover {
  border: 2px solid lightgrey;
  box-shadow: 0px 0px 20px -17px;
}

.nuxdy-form-select:focus {
  border: 2px solid grey;
}

/* ----------------------------------------------------------- */

.nuxdy-form-checkbox {
  height: 1rem;
  width: 1rem;
  border-radius: 0.25rem;
  border-color: #d1d5db;
  color: #6366f1;
  margin-right: 0.5rem;
}

.nuxdy-form-checkbox:focus {
  box-shadow: 0 0 0 2px #6366f1;
}

/* ----------------------------------------------------------- */

.nuxdy-form-radio {
  height: 1rem;
  width: 1rem;
  border-color: #d1d5db;
  color: #6366f1;
  margin-right: 0.5rem;
}

.nuxdy-form-radio:focus {
  box-shadow: 0 0 0 2px #6366f1;
}

/* ----------------------------------------------------------- */

.nuxdy-form-error {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: #dc2626;
}

/* ----------------------------------------------------------- */

.nuxdy-form-title {
  font-size: 1.25rem;
  font-weight: 700;
  margin-bottom: 1rem;
}

.nuxdy-form-description {
  color: #4b5563;
  margin-bottom: 1.5rem;
}

/* ----------------------------------------------------------- */

.nuxdy-form-actions {
  display: flex;
  gap: 1rem;
  margin-top: 1.5rem;
}

.nuxdy-form-button {
  display: inline-flex;
  justify-content: center;
  border-radius: 0.375rem;
  border-width: 1px;
  background-color: #4f46e5;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: white;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

.nuxdy-form-button:hover,
.nuxdy-form-button:focus {
  background-color: #4338ca;
}

.nuxdy-form-button:active,
.nuxdy-form-button:focus-visible {
  outline-color: transparent; /* ensures we have focus indicator on high contrast themes */
  outline-width: 2px;
  outline-style: solid;
  box-shadow: 0 0 0 2px #c7d2fe;
}

.nuxdy-form-group {
  padding: 1rem;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
  margin-bottom: 1rem;
}

.nuxdy-form-list-item {
  position: relative;
  padding: 1rem;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
  margin-bottom: 1rem;
}

.nuxdy-form-remove-button {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  color: #ef4444;
}

.nuxdy-form-remove-button:hover {
  color: #b91c1c;
}

Events

The NuxdyForm component emits the following events:

  • submit: Emitted when the form is submitted with valid data
  • reset: Emitted when the form is reset
  • validation-error: Emitted when there are validation errors

Development

# Install dependencies
npm install

# Start development server
npm run dev

# Build the library
npm run build

# Run tests
npm run test

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors