Form Components

JavaScript components for autocomplete suggestions and form validation.

Autocomplete Manager

Autocomplete suggestions with keyboard navigation.

  • Uni ted States
  • Uni ted Kingdom
  • Uni ted Arab Emirates
  • Product Name $99.00
  • Another Product $149.00
HTML
<!-- Basic autocomplete -->
        <div style="position: relative; max-width: 400px">
            <input
                type="text"
                data-ss="autocomplete"
                data-ss-autocomplete-min-chars="2"
                placeholder="Search countries..."
                style="
                    width: 100%;
                    padding: 12px 16px;
                    border: 1px solid var(--color_line_secondary);
                    border-radius: 8px;
                    font-size: 16px;
                "
            />

            <!-- Suggestions dropdown (shown when typing) -->
            <ul
                class="ss-c-autocomplete-suggestions"
                style="
                    position: absolute;
                    top: 100%;
                    left: 0;
                    right: 0;
                    margin: 4px 0 0;
                    padding: 8px 0;
                    background: white;
                    border: 1px solid var(--color_line_secondary);
                    border-radius: 8px;
                    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
                    list-style: none;
                    max-height: 240px;
                    overflow-y: auto;
                "
            >
                <li style="padding: 10px 16px; cursor: pointer">
                    <span style="font-weight: 500">Uni</span>
                    ted States
                </li>
                <li
                    style="
                        padding: 10px 16px;
                        cursor: pointer;
                        background: var(--color_fill_secondary);
                    "
                >
                    <span style="font-weight: 500">Uni</span>
                    ted Kingdom
                </li>
                <li style="padding: 10px 16px; cursor: pointer">
                    <span style="font-weight: 500">Uni</span>
                    ted Arab Emirates
                </li>
            </ul>
        </div>

        <!-- Autocomplete with API fetch -->
        <div style="position: relative; max-width: 400px; margin-top: 24px">
            <label
                style="display: block; margin-bottom: 8px; font-weight: 500"
            >
                Search Users
            </label>
            <div style="position: relative">
                <input
                    type="text"
                    data-ss="autocomplete"
                    data-ss-autocomplete-min-chars="1"
                    data-ss-autocomplete-url="/api/users/search"
                    placeholder="Type a name..."
                    style="
                        width: 100%;
                        padding: 12px 16px 12px 44px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                        font-size: 16px;
                    "
                />
                <span
                    style="
                        position: absolute;
                        left: 16px;
                        top: 50%;
                        transform: translateY(-50%);
                        opacity: 0.5;
                    "
                >
                    ⌕
                </span>
            </div>
        </div>

        <!-- Autocomplete with custom template -->
        <div style="position: relative; max-width: 400px; margin-top: 24px">
            <input
                type="text"
                data-ss="autocomplete"
                placeholder="Search products..."
                style="
                    width: 100%;
                    padding: 12px 16px;
                    border: 1px solid var(--color_line_secondary);
                    border-radius: 8px;
                "
            />

            <ul
                class="ss-c-autocomplete-suggestions"
                style="
                    position: absolute;
                    top: 100%;
                    left: 0;
                    right: 0;
                    margin: 4px 0 0;
                    padding: 8px;
                    background: white;
                    border: 1px solid var(--color_line_secondary);
                    border-radius: 8px;
                    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
                    list-style: none;
                "
            >
                <li
                    style="
                        padding: 8px;
                        cursor: pointer;
                        display: flex;
                        gap: 12px;
                        align-items: center;
                        border-radius: 6px;
                    "
                >
                    <div
                        style="
                            width: 48px;
                            height: 48px;
                            background: var(--color_fill_secondary);
                            border-radius: 8px;
                        "
                    ></div>
                    <div>
                        <strong style="display: block">Product Name</strong>
                        <span style="font-size: 14px; opacity: 0.6">
                            $99.00
                        </span>
                    </div>
                </li>
                <li
                    style="
                        padding: 8px;
                        cursor: pointer;
                        display: flex;
                        gap: 12px;
                        align-items: center;
                        border-radius: 6px;
                        background: var(--color_fill_secondary);
                    "
                >
                    <div
                        style="
                            width: 48px;
                            height: 48px;
                            background: var(--color_line_secondary);
                            border-radius: 8px;
                        "
                    ></div>
                    <div>
                        <strong style="display: block">Another Product</strong>
                        <span style="font-size: 14px; opacity: 0.6">
                            $149.00
                        </span>
                    </div>
                </li>
            </ul>
        </div>

Form Validator

Form validation with customizable rules and real-time feedback.

Min 8 characters with mixed case and numbers
HTML
<form
            data-ss="validate"
            data-ss-validate-on-blur="true"
            style="
                max-width: 500px;
                display: flex;
                flex-direction: column;
                gap: 20px;
            "
        >
            <!-- Email field -->
            <div class="ss-c-form-field">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Email *
                </label>
                <input
                    type="email"
                    name="email"
                    data-ss-validate-required="Email is required"
                    data-ss-validate-email="Please enter a valid email"
                    style="
                        width: 100%;
                        padding: 12px 16px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                    "
                />
                <span
                    class="ss-c-form-field__error"
                    style="
                        display: none;
                        color: var(--color_state_error);
                        font-size: 14px;
                        margin-top: 4px;
                    "
                ></span>
            </div>

            <!-- Password field -->
            <div class="ss-c-form-field">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Password *
                </label>
                <input
                    type="password"
                    name="password"
                    data-ss-validate-required="Password is required"
                    data-ss-validate-min-length="8"
                    data-ss-validate-pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*\d)"
                    data-ss-validate-pattern-message="Must contain uppercase, lowercase, and number"
                    style="
                        width: 100%;
                        padding: 12px 16px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                    "
                />
                <span
                    class="ss-c-form-field__hint"
                    style="
                        display: block;
                        font-size: 13px;
                        opacity: 0.6;
                        margin-top: 4px;
                    "
                >
                    Min 8 characters with mixed case and numbers
                </span>
            </div>

            <!-- Confirm password -->
            <div class="ss-c-form-field">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Confirm Password *
                </label>
                <input
                    type="password"
                    name="confirmPassword"
                    data-ss-validate-required="Please confirm your password"
                    data-ss-validate-match="password"
                    data-ss-validate-match-message="Passwords do not match"
                    style="
                        width: 100%;
                        padding: 12px 16px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                    "
                />
            </div>

            <!-- Terms checkbox -->
            <div class="ss-c-form-field">
                <label
                    style="
                        display: flex;
                        align-items: flex-start;
                        gap: 8px;
                        cursor: pointer;
                    "
                >
                    <input
                        type="checkbox"
                        name="terms"
                        data-ss-validate-required="You must accept the terms"
                        style="margin-top: 4px"
                    />
                    <span>
                        I agree to the
                        <a href="#">Terms of Service</a>
                        and
                        <a href="#">Privacy Policy</a>
                        *
                    </span>
                </label>
            </div>

            <button
                type="submit"
                style="
                    padding: 14px 28px;
                    background: var(--color_fill_primary);
                    color: white;
                    border: none;
                    border-radius: 8px;
                    font-weight: 600;
                    cursor: pointer;
                "
            >
                Create Account
            </button>
        </form>

Validation States

Visual feedback for different validation states.

Email is valid
Please enter a valid email address
Password is weak. Consider using a stronger one.
HTML
<div
            style="
                display: flex;
                flex-direction: column;
                gap: 24px;
                max-width: 400px;
            "
        >
            <!-- Default state -->
            <div class="ss-c-form-field">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Default
                </label>
                <input
                    type="text"
                    placeholder="Enter value..."
                    style="
                        width: 100%;
                        padding: 12px 16px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                    "
                />
            </div>

            <!-- Focus state -->
            <div class="ss-c-form-field">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Focus
                </label>
                <input
                    type="text"
                    placeholder="Focused input..."
                    style="
                        width: 100%;
                        padding: 12px 16px;
                        border: 2px solid var(--color_fill_primary);
                        border-radius: 8px;
                        outline: none;
                        box-shadow: 0 0 0 3px
                            rgba(var(--color_fill_primary_rgb), 0.1);
                    "
                />
            </div>

            <!-- Valid state -->
            <div class="ss-c-form-field is-valid">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Valid
                </label>
                <div style="position: relative">
                    <input
                        type="text"
                        value="valid@email.com"
                        style="
                            width: 100%;
                            padding: 12px 40px 12px 16px;
                            border: 2px solid var(--color_state_success);
                            border-radius: 8px;
                            background: rgba(34, 197, 94, 0.05);
                        "
                    />
                    <span
                        style="
                            position: absolute;
                            right: 12px;
                            top: 50%;
                            transform: translateY(-50%);
                            color: var(--color_state_success);
                        "
                    >
                        ✓
                    </span>
                </div>
                <span
                    style="
                        display: block;
                        color: var(--color_state_success);
                        font-size: 14px;
                        margin-top: 4px;
                    "
                >
                    Email is valid
                </span>
            </div>

            <!-- Invalid state -->
            <div class="ss-c-form-field is-invalid">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Invalid
                </label>
                <div style="position: relative">
                    <input
                        type="text"
                        value="invalid-email"
                        style="
                            width: 100%;
                            padding: 12px 40px 12px 16px;
                            border: 2px solid var(--color_state_error);
                            border-radius: 8px;
                            background: rgba(239, 68, 68, 0.05);
                        "
                    />
                    <span
                        style="
                            position: absolute;
                            right: 12px;
                            top: 50%;
                            transform: translateY(-50%);
                            color: var(--color_state_error);
                        "
                    >
                        ✕
                    </span>
                </div>
                <span
                    style="
                        display: block;
                        color: var(--color_state_error);
                        font-size: 14px;
                        margin-top: 4px;
                    "
                >
                    Please enter a valid email address
                </span>
            </div>

            <!-- Warning state -->
            <div class="ss-c-form-field is-warning">
                <label
                    style="
                        display: block;
                        margin-bottom: 6px;
                        font-weight: 500;
                    "
                >
                    Warning
                </label>
                <input
                    type="text"
                    value="weak_password"
                    style="
                        width: 100%;
                        padding: 12px 16px;
                        border: 2px solid var(--color_state_warning);
                        border-radius: 8px;
                        background: rgba(245, 158, 11, 0.05);
                    "
                />
                <span
                    style="
                        display: block;
                        color: var(--color_state_warning);
                        font-size: 14px;
                        margin-top: 4px;
                    "
                >
                    Password is weak. Consider using a stronger one.
                </span>
            </div>
        </div>

Password Toggle

Show/hide password functionality.

HTML
<div style="max-width: 400px">
            <label
                style="display: block; margin-bottom: 6px; font-weight: 500"
            >
                Password
            </label>
            <div style="position: relative">
                <input
                    type="password"
                    id="userPassword"
                    value="mysecretpassword"
                    style="
                        width: 100%;
                        padding: 12px 48px 12px 16px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                    "
                />
                <button
                    type="button"
                    data-password-toggle="userPassword"
                    style="
                        position: absolute;
                        right: 8px;
                        top: 50%;
                        transform: translateY(-50%);
                        padding: 8px;
                        background: none;
                        border: none;
                        cursor: pointer;
                        opacity: 0.6;
                    "
                >
                    ◉
                </button>
            </div>
        </div>

        <!-- Password visible state -->
        <div style="max-width: 400px; margin-top: 16px">
            <label
                style="display: block; margin-bottom: 6px; font-weight: 500"
            >
                Password (Visible)
            </label>
            <div style="position: relative">
                <input
                    type="text"
                    value="mysecretpassword"
                    style="
                        width: 100%;
                        padding: 12px 48px 12px 16px;
                        border: 1px solid var(--color_line_secondary);
                        border-radius: 8px;
                    "
                />
                <button
                    type="button"
                    style="
                        position: absolute;
                        right: 8px;
                        top: 50%;
                        transform: translateY(-50%);
                        padding: 8px;
                        background: none;
                        border: none;
                        cursor: pointer;
                    "
                >
                    ◉
                </button>
            </div>
        </div>

JavaScript API

Programmatic control of form components.

JavaScript
<script>
            // AutocompleteManager
            import { AutocompleteManager } from "stylescape";

            const autocomplete = new AutocompleteManager(inputElement, {
                minChars: 2,
                debounce: 300,
                maxResults: 10,
                source: async (query) => {
                    const response = await fetch(`/api/search?q=${query}`);
                    return response.json();
                },
                renderItem: (item) => `
        <div class="ss-c-autocomplete-item">
            <img src="${item.avatar}" alt="">
            <span>${item.name}</span>
        </div>
    `,
                onSelect: (item) => {
                    console.log("Selected:", item);
                },
            });

            autocomplete.setSource(newDataArray);
            autocomplete.clear();
            autocomplete.destroy();

            // FormValidator
            import { FormValidator } from "stylescape";

            const validator = new FormValidator(formElement, {
                validateOnBlur: true,
                validateOnInput: false,
                showErrors: true,
                rules: {
                    email: {
                        required: true,
                        email: true,
                        message: "Please enter a valid email",
                    },
                    password: {
                        required: true,
                        minLength: 8,
                        pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
                        message:
                            "Password must be 8+ chars with mixed case and numbers",
                    },
                    confirmPassword: {
                        required: true,
                        match: "password",
                        message: "Passwords must match",
                    },
                },
                onSubmit: async (data, form) => {
                    // Handle valid form submission
                    await submitForm(data);
                },
                onError: (errors) => {
                    console.log("Validation errors:", errors);
                },
            });

            validator.validate(); // Validate all fields
            validator.validateField("email"); // Validate single field
            validator.isValid(); // Check if form is valid
            validator.getErrors(); // Get all error messages
            validator.reset(); // Reset validation state
            validator.setFieldError("email", "Custom error");
        </script>