Forms

Формы используют `.form-group`, `.label` и `.input`. Ошибки задаются на label через `.error`, а пояснение выводится соседним `.input-info`.

Field cannot be empty
Looks good
Check before publishing
Date & Time
Fieldset

Upload files

Attach documents, archives, screenshots or product images for review.

Max 12 MB
Field cannot be empty
frontend vue
Press Enter to add, Backspace to remove last
Fields
Forms HTML
<div class="form-group">
  <label class="label error">
    Project name
    <i class="ph ph-user"></i>
    <input class="input" type="text" placeholder="Launch Plan">
  </label>
  <div class="input-info">
    <i class="ph ph-warning-circle"></i>
    Field cannot be empty
  </div>
</div>

<fieldset class="fieldset">
  <legend class="legend">Fieldset</legend>
  <label class="label success">
    Validated
    <input class="input" type="text" value="Release Plan">
  </label>
</fieldset>

<label class="file-upload">
  Upload file
  <input type="file">
</label>

<fieldset class="fieldset">
  <legend class="legend">Date & Time</legend>
  <div class="form-grid">
    <label class="label">
      Date
      <i class="ph ph-calendar-blank"></i>
      <input class="input input-date" type="date" value="2026-04-23" data-date-picker>
    </label>
    <label class="label">
      Time
      <i class="ph ph-clock"></i>
      <input class="input input-time" type="time" value="14:30" data-date-picker>
    </label>
    <label class="label">
      Date & time
      <i class="ph ph-calendar-dots"></i>
      <input class="input input-datetime" type="datetime-local" value="2026-04-23T14:30" data-date-picker>
    </label>
  </div>
</fieldset>

<div class="file-upload-panel">
  <form class="file-upload-form" enctype="multipart/form-data">
    <div class="file-upload-header">
      <div class="file-upload-heading">
        <h3 class="file-upload-title">Upload files</h3>
        <p class="file-upload-description">Attach documents, archives or images.</p>
      </div>
      <span class="badge badge-info">Max 12 MB</span>
    </div>

    <label class="file-upload-dropzone">
      <span class="file-upload-icon" aria-hidden="true">
        <i class="ph ph-cloud-arrow-up"></i>
      </span>
      <span class="file-upload-body">
        <span class="file-upload-primary">Choose files</span>
        <span class="file-upload-secondary">Images get thumbnails, other files show their type</span>
      </span>
      <input type="file" name="files" multiple data-file-upload-input>
    </label>

    <div class="file-upload-preview" data-file-upload-preview hidden></div>

    <div class="file-upload-actions">
      <button class="btn btn-secondary btn-small" type="reset">Reset</button>
      <button class="btn btn-accent btn-small" type="submit">Upload</button>
    </div>
  </form>
</div>
Tag Input HTML
<div class="tag-input">
  <div class="tag-input-wrap">
    <span class="chip chip-secondary">frontend
      <button class="chip-remove" type="button" aria-label="Remove frontend">
        <i class="ph ph-x"></i>
      </button>
    </span>
    <input type="text" class="tag-input-field" placeholder="Add item…">
  </div>
</div>
<div class="input-info"><i class="ph ph-info"></i> Press Enter to add</div>
Vue: GnTagInput
<GnTagInput
  v-model="tags"
  label="Tags"
  placeholder="Add item…"
  help="Press Enter to add, Backspace to remove last"
  separator=","
  :unique="true"
  :max-items="10"
/>
Repeater HTML
<div class="repeater">
  <div class="repeater-header">
    <span class="repeater-title">Fields</span>
    <button class="btn btn-secondary btn-small" type="button">Add field</button>
  </div>
  <div class="repeater-list">
    <div class="repeater-item">
      <div class="repeater-item-body form-grid">...</div>
      <div class="repeater-item-actions">
        <button class="btn-icon btn-icon-sm" type="button">...</button>
      </div>
    </div>
  </div>
</div>
Vue: GnRepeater
<GnRepeater v-model="fields" label="Fields" add-label="Add field">
  <template #item="{ item, index, remove }">
    <div class="form-grid">
      <GnInput v-model="item.name" label="Name" />
      <GnInput v-model="item.value" label="Value" />
    </div>
  </template>
</GnRepeater>