Form

Component

Interactive examples and API documentation

Basic Form
A basic form example using hakumi_form_with with text fields, password, and textarea.
Enter your unique username
Must be at least 8 characters
Tell us about yourself
Code
<%= hakumi_form_with(url: "/demo", method: :post, html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :basic_username,
                   label: "Username",
                   caption: "Enter your unique username",
                   placeholder: "username",
                   required: true %>

  <%= f.text_field :basic_email,
                   label: "Email",
                   caption: "We'll never share your email",
                   placeholder: "email@example.com",
                   required: true %>

  <%= f.password_field :basic_password,
                       label: "Password",
                       caption: "Must be at least 8 characters",
                       placeholder: "Enter password",
                       required: true %>

  <%= f.text_area :basic_bio,
                  label: "Bio",
                  caption: "Tell us about yourself",
                  rows: 4,
                  placeholder: "Write something..." %>

  <%= f.submit "Create Account" %>
<% end %>
Input Sizes
Inputs come in three sizes: small, middle (default), and large.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :large_input,
                   label: "Large Input",
                   size: :large,
                   placeholder: "Large size" %>

  <%= f.text_field :middle_input,
                   label: "Middle Input (Default)",
                   size: :middle,
                   placeholder: "Middle size" %>

  <%= f.text_field :small_input,
                   label: "Small Input",
                   size: :small,
                   placeholder: "Small size" %>
<% end %>
Input Features
Inputs support prefixes, suffixes, icons, and clear buttons.
$ USD
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :amount,
                   label: "Prefix/Suffix Text",
                   prefix: "$",
                   suffix: "USD",
                   placeholder: "0.00" %>

  <%= f.text_field :search,
                   label: "Prefix/Suffix Icons",
                   prefix_icon: :search,
                   suffix_icon: :info_circle,
                   placeholder: "Search..." %>

  <%= f.text_field :clearable,
                   label: "Clear Button",
                   placeholder: "Type to see clear icon...",
                   allow_clear: true %>
<% end %>
Number Input
Numeric input with min, max, and step validation.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.number_field :age,
                     label: "Age",
                     min: 18,
                     max: 99,
                     step: 1,
                     placeholder: "18-99" %>

  <%= f.number_field :quantity,
                     label: "Quantity",
                     min: 1,
                     max: 10,
                     value: 1 %>
<% end %>
TextArea Features
Multi-line text input with optional character count.
Maximum 200 characters
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_area :description,
                  label: "Description",
                  rows: 4,
                  placeholder: "Enter your description here..." %>

  <%= f.text_area :limited_text,
                  label: "With Character Count",
                  caption: "Maximum 200 characters",
                  rows: 4,
                  show_count: true,
                  maxlength: 200,
                  placeholder: "Type here..." %>
<% end %>
Password Features
Password input with visibility toggle.
Click the eye icon to toggle visibility
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.password_field :password_demo,
                       label: "Password",
                       caption: "Click the eye icon to toggle visibility",
                       prefix_icon: :lock,
                       placeholder: "Enter password" %>
<% end %>
Input Group
Input groups allow multiple inputs to be attached together.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= render Hakumi::Form::Item::Component.new(label: "Compact Group") do %>
    <%= render Hakumi::Space::Compact::Component.new(block: true) do %>
      <%= f.text_field :site, style: "width: 20%", value: "https://" %>
      <%= f.text_field :domain, style: "width: 55%", value: "mysite" %>
      <%= f.text_field :suffix, style: "width: 25%", value: ".com" %>
    <% end %>
  <% end %>
<% end %>
Form Buttons
Submit buttons with different types and sizes.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= render(Hakumi::Space::Component.new(size: :middle)) do %>
    <%= f.submit "Primary", type: :primary %>
    <%= f.submit "Default", type: :default %>
    <%= f.submit "Large", type: :primary, size: :large %>
    <%= f.submit "Small", type: :primary, size: :small %>
  <% end %>
<% end %>
Inline Form
Inline forms are used to save vertical space.
Code
<%= hakumi_form_with(url: "/demo", layout: :inline, html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :inline_username, placeholder: "Username", prefix_icon: :user %>
  <%= f.password_field :inline_password, placeholder: "Password", prefix_icon: :lock %>
  <%= f.submit "Log in" %>
<% end %>
Disabled and Readonly
Inputs can be disabled or readonly.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :disabled_input,
                   label: "Disabled Input",
                   value: "This field is disabled",
                   disabled: true %>

  <%= f.text_field :readonly_input,
                   label: "Readonly Input",
                   value: "This field is readonly",
                   readonly: true %>
<% end %>
Server-side Validation Errors
How server-side errors are displayed (simulated).
Code
<%
  user = PlaygroundHelper::DemoUser.new(username: "taken_user", email: "invalid-email")
  user.errors.add(:username, "Username is already taken")
  user.errors.add(:email, "Invalid email format")
%>

<%= hakumi_form_with(model: user, url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :username,
                   label: "Username",
                   required: true %>

  <%= f.text_field :email,
                   label: "Email",
                   required: true %>
<% end %>
Client-side Validation: Required
Basic required field validation with custom error message.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :req_username,
                   label: "Username",
                   placeholder: "Enter username",
                   rules: [{ required: true, message: "Username is required" }] %>
  <%= f.submit "Submit" %>
<% end %>
Client-side Validation: Length
Validate minimum and maximum length.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :length_username,
                   label: "Username",
                   placeholder: "3-20 characters",
                   rules: [
                     { required: true },
                     { min_length: 3, message: "Minimum 3 characters" },
                     { max_length: 20, message: "Maximum 20 characters" }
                   ] %>
  <%= f.submit "Submit" %>
<% end %>
Client-side Validation: Email
Built-in email validation.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :val_email,
                   label: "Email",
                   placeholder: "email@example.com",
                   rules: [
                     { required: true, message: "Email is required" },
                     { email: true, message: "Invalid email format" }
                   ] %>
  <%= f.submit "Submit" %>
<% end %>
Client-side Validation: Pattern
Validate using regular expressions.
Only letters, numbers, and underscores allowed
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :pattern_username,
                   label: "Username",
                   caption: "Only letters, numbers, and underscores allowed",
                   placeholder: "user_name123",
                   rules: [
                     { required: true },
                     { pattern: "^[a-zA-Z0-9_]+$", message: "Invalid characters" }
                   ] %>
  <%= f.submit "Submit" %>
<% end %>
Client-side Validation: Password Confirmation
Automatic validation when dependent fields change using validation rules.
Enter a password
Will auto-validate when password changes
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.password_field :confirm_password,
                       label: "Password",
                       caption: "Enter a password",
                       placeholder: "Enter password",
                       rules: [{ required: true, message: "Password is required" }] %>

  <%= f.password_field :confirm_password_confirmation,
                       label: "Confirm Password",
                       caption: "Will auto-validate when password changes",
                       placeholder: "Re-enter password",
                       rules: [
                         { required: true, message: "Please confirm your password" },
                         { match: "confirm_password", message: "Passwords do not match" }
                       ] %>

  <%= f.submit "Register" %>
<% end %>
Client-side Validation: Combined Rules
Multiple fields with different validation rules.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
  <%= f.text_field :combined_username,
                   label: "Username",
                   placeholder: "user_name123",
                   rules: [
                     { required: true, message: "Required" },
                     { min_length: 3, message: "Min 3 chars" },
                     { max_length: 20, message: "Max 20 chars" },
                     { pattern: "^[a-zA-Z0-9_]+$", message: "Letters, numbers, _ only" }
                   ] %>

  <%= f.text_field :combined_email,
                   label: "Email",
                   placeholder: "email@example.com",
                   rules: [
                     { required: true },
                     { email: true }
                   ] %>

  <%= f.submit "Submit" %>
<% end %>

Form Helper API (hakumi_form_with)

Prop Type Default Description
model ActiveRecord or PORO - Object used for model-based forms.
url String or Hash - URL for non-model forms.
method :get | :post | :patch | :put or :delete :post HTTP verb passed to form_with.
layout :horizontal | :vertical or :inline - Applies Hakumi form layout classes.
builder Class Hakumi::FormBuilder Custom builder (defaults to Hakumi).
html Hash - HTML attributes for the <form> tag (class merged with `hakumi-form`).
block Proc required Yields the form builder instance.

Form::Item API

Prop Type Default Description
label String - Optional label rendered above the control.
content slot Slot - Form control (input, select, etc.).
**html_options Keyword args - Classes/data attributes merged into `.hakumi-form-item`. Pass as kwargs (e.g., `class:`, `style:`, `data:`).