<div id="form-38648-51837" class="form">

    <form id="form-38648-51837-form" class="form__form" method="post" enctype="multipart/form-data" accept-charset="utf-8">

        <div class="form__title">
            <h2 class="headline headline--3"><span class="headline__text">Das ist ein Formular</span></h2>
        </div>

        <div class="form__progress">
            <div class="progress">
                <div class="progress__progress" style="width: 50%" role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
                    <span class="progress__label">50%</span>
                </div>
            </div>
        </div>

        <div class="form__pages">
            <ol class="form__tabs" role="tablist">

                <li class="form__tab form__tab--current" role="presentation">
                    <span class="form__tab-link u-underline" role="tab" aria-selected="true">Erste Seite</span>
                </li>

                <li class="form__tab" role="presentation">
                    <span class="form__tab-link u-underline" role="tab">Zweite Seite</span>
                </li>
            </ol>

            <div class="form__page form__page--current">
                <div class="form__page-title">
                    <span class="form__page-title-link u-underline" aria-selected="true">Erste Seite</span>
                </div>

                <fieldset class="form__page-fields">
                    <legend class="form__page-legend form__page-legend--hidden">Erste Seite</legend>

                    <div class="form__row">

                        <div id="form-38648-51837-field-98170-49006" class="field form__field">
                            <label class="field__label" for="form-38648-51837-field-98170-49006-control">
                                <span class="label">Text-Feld<span aria-hidden="true" class="label__required" title="Notwendig">*</span></span>
                            </label>

                            <div id="form-38648-51837-field-98170-49006-errors" class="field__errors" hidden>
                                <div class="notice notice--error">
                                    <svg class="icon icon--caution notice__icon" viewBox="0 0 200 200" aria-hidden="true">
                                        <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#caution"></use>
                                    </svg>
                                    <span class="notice__text"></span>
                                </div>
                            </div>

                            <div class="field__controls field__controls--stacked">
                                <div class="field__control">
                                    <div class="input">
                                        <div class="input__inner">
                                            <input class="input__input input__input--text" id="form-38648-51837-field-98170-49006-control" name="text-field" required aria-describedby="form-38648-51837-field-98170-49006-instructions" aria-required="true" type="text" />

                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="field__footer">
                                <div class="field__instructions" id="form-38648-51837-field-98170-49006-instructions">
                                    <div class="notice notice--instructions">
                                        <svg class="icon icon--info-alt notice__icon" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#info-alt"></use>
                                        </svg>
                                        <span class="notice__text">Das ist eine Beschreibung</span>
                                    </div>
                                </div>

                            </div>
                        </div>
                    </div>

                    <div class="form__buttons form__buttons--right">

                        <div class="form__button form__button--submit">
                            <button class="button u-underline" type="button">Absenden</button>
                        </div>
                    </div>
                </fieldset>
            </div>

            <div class="form__page">
                <div class="form__page-title">
                    <span class="form__page-title-link u-underline">Zweite Seite</span>
                </div>

                <fieldset class="form__page-fields form__page-fields--hidden">
                    <legend class="form__page-legend form__page-legend--hidden">Zweite Seite</legend>

                    <div class="form__row">

                        <div id="form-38648-51837-field-53705-49011" class="field form__field">
                            <label class="field__label" for="form-38648-51837-field-53705-49011-control">
                                <span class="label">Text-Feld<span aria-hidden="true" class="label__required" title="Notwendig">*</span></span>
                            </label>

                            <div id="form-38648-51837-field-53705-49011-errors" class="field__errors" hidden>
                                <div class="notice notice--error">
                                    <svg class="icon icon--caution notice__icon" viewBox="0 0 200 200" aria-hidden="true">
                                        <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#caution"></use>
                                    </svg>
                                    <span class="notice__text"></span>
                                </div>
                            </div>

                            <div class="field__controls field__controls--stacked">
                                <div class="field__control">
                                    <div class="input">
                                        <div class="input__inner">
                                            <input class="input__input input__input--text" id="form-38648-51837-field-53705-49011-control" name="text-field" required aria-describedby="form-38648-51837-field-53705-49011-instructions" aria-required="true" type="text" />

                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="field__footer">
                                <div class="field__instructions" id="form-38648-51837-field-53705-49011-instructions">
                                    <div class="notice notice--instructions">
                                        <svg class="icon icon--info-alt notice__icon" viewBox="0 0 200 200" aria-hidden="true">
                                            <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#info-alt"></use>
                                        </svg>
                                        <span class="notice__text">Das ist eine Beschreibung</span>
                                    </div>
                                </div>

                            </div>
                        </div>
                    </div>

                    <div class="form__buttons form__buttons--right">

                        <div class="form__button form__button--submit">
                            <button class="button u-underline" type="button">Absenden</button>
                        </div>
                    </div>
                </fieldset>
            </div>
        </div>

    </form>

</div>
{% set id = id ??? html_id('form') %}
{% set showForm = showForm ?? true %}
{% set submitActionMessagePosition = submitActionMessagePosition ?? 'top-form' %}
{% set errorMessagePosition = errorMessagePosition ?? 'top-form' %}
{% set progressPosition = progressPosition ?? 'end' %}
{% set pages = pages ?? [] %}
{% set showTabs = showTabs ?? false %}

<div {{ html_attributes({
  id: id,
  class: 'form',
}, attrs ?? {}) }}>
  {% if submitActionMessagePosition == 'top-form' and submitActionMessage|default %}
    <div class="form__alert form__alert--success">
      {% include '@alert' with {
        type: 'success',
        text: submitActionMessage,
      } only %}
    </div>
  {% endif %}

  {% if errorMessagePosition == 'top-form' and errorMessage|default %}
    <div class="form__alert form__alert--error">
      {% include '@alert' with {
        type: 'error',
        text: errorMessage,
      } only %}
    </div>
  {% endif %}

  {% if showForm %}
    <form {{ html_attributes({
      id: 'form' | namespaceInputId(id),
      class: 'form__form',
      action: action ??? '',
      method: method ??? 'post',
      enctype: 'multipart/form-data',
      'accept-charset': 'utf-8',
    }, formAttrs ?? {}) }}>
      {{ csrf|default ? csrfInput({ autocomplete: 'false' }) }}
      {{ actionUrl|default ? actionInput(actionUrl) }}
      {{ redirectUrl|default ? redirectInput(redirectUrl) }}

      {% for name, value in hiddenInputs|default %}
        {{ value ? hiddenInput(name, value) }}
      {% endfor %}

      {% if title|default %}
        <div class="form__title">
          {% include '@headline' with {
            text: title,
            level: 2,
            size: 3,
          } only %}
        </div>
      {% endif %}

      {% if introText|default %}
        <div class="form__intro-text">
          {{ introText | componentize }}
        </div>
      {% endif %}

      {% if progressPosition == 'start' and progress|default %}
        <div class="form__progress">
          {% include '@progress' with {
            current: progress,
          } only %}
        </div>
      {% endif %}

      {# Errors #}
      {% if errors|default %}
        <div class="form__errors">
          {% include '@notice' with {
            type: 'error',
            text: errors | join('<br>'),
          } only %}
        </div>
      {% endif %}

      {# Tabs #}
      <div class="form__pages">
        {% if pages|length > 1 and showTabs %}
          <ol class="form__tabs" role="tablist">
            {% for page in pages %}
              {% set isCurrent = page.isCurrent ?? loop.first %}

              <li {{ html_attributes({
                class: {
                  'form__tab': true,
                  'form__tab--current': isCurrent,
                  'form__tab--errors': page.hasErrors ?? false,
                },
                role: 'presentation',
              }, page.tabAttrs ?? {}) }}>
                {% set tag = not isCurrent and page.url|default ? 'a' : 'span' %}
                <{{ tag }} {{ html_attributes({
                  class: ['form__tab-link', 'u-underline'],
                  href: not isCurrent and page.url|default ? page.url,
                  role: 'tab',
                  'aria-selected': isCurrent ? 'true',
                  'tabindex': isCurrent ? '0',
                }) }}>
                  {{- page.title -}}
                </{{ tag }}>
              </li>
            {% endfor %}
          </ol>
        {% endif %}

        {% for page in pages %}
          {% set isCurrent = page.isCurrent ?? loop.first %}

          <div {{ html_attributes({
            class: {
              'form__page': true,
              'form__page--current': isCurrent,
              'form__page--errors': page.hasErrors ?? false,
            },
          }) }}>
            {% if showTabs %}
              <div class="form__page-title">
                {% set tag = not isCurrent and page.url|default ? 'a' : 'span' %}
                <{{ tag }} {{ html_attributes({
                  class: ['form__page-title-link', 'u-underline'],
                  href: not isCurrent and page.url|default ? page.url,
                  'aria-selected': isCurrent ? 'true',
                  'tabindex': isCurrent ? '0',
                }) }}>
                  {{- page.title -}}
                </{{ tag }}>
              </div>
            {% endif %}

            <fieldset class="form__page-fields{{ page.hidden|default ? ' form__page-fields--hidden' }}">
              <legend {{ html_attributes({
                class: {
                  'form__page-legend': true,
                  'form__page-legend--hidden': not page.showTitle|default,
                },
              }) }}>
                {{- page.title ?? 'Form page' -}}
              </legend>

              {% for row in page.fields %}
                <div {{ html_attributes({
                  class: 'form__row',
                  hidden: row | filter(field => field.hidden|default) | length == row | length,
                }) }}>
                  {% for field in row %}
                    {% include '@field' with field | merge({
                      id: field.id | default(html_id('field')) | namespaceInputId(id),
                      formId: id,
                      attrs: field.attrs | default({}) | merge({
                        class: html_classes(field.attrs.class ?? '', 'form__field'),
                      }),
                    }) only %}
                  {% endfor %}
                </div>
              {% endfor %}

              {{ page.captchas | default('') | raw }}

              {% if submitActionMessagePosition == 'bottom-form' and submitActionMessage|default %}
                <div class="form__alert form__alert--success">
                  {% include '@alert' with {
                    type: 'success',
                    text: submitActionMessage,
                  } only %}
                </div>
              {% endif %}

              {% if errorMessagePosition == 'bottom-form' and errorMessage|default %}
                <div class="form__alert form__alert--error">
                  {% include '@alert' with {
                    type: 'error',
                    text: errorMessage,
                  } only %}
                </div>
              {% endif %}

              {% if page.buttons|default %}
                <div class="form__buttons {{ "form__buttons--#{page.buttonsPosition ?? 'right'}" }}">
                  {% for button in page.buttons %}
                    {% set buttonAction = button.action %}
                    {% set button = button | without('action') %}

                    <div {{ html_attributes({
                      class: "form__button form__button--#{buttonAction}",
                    }, button.containerAttrs ?? {}) }}>
                      {% include button.type|default == 'link' ? '@icon-button' : '@button' with button only %}
                    </div>
                  {% endfor %}
                </div>
              {% endif %}
            </fieldset>
          </div>
        {% endfor %}
      </div>

      {% if buttons|default %}
        <div class="form__buttons {{ "form__buttons--#{buttonsPosition ?? 'right'}" }}">
          {% for button in buttons %}
            {% set buttonAction = button.action %}
            {% set button = button | withoutKey('action') %}

            <div {{ html_attributes({
              class: "form__button form__button--#{buttonAction}",
            }, button.containerAttrs ?? {}) }}>
              {% include button.type|default == 'link' ? '@icon-button' : '@button' with button only %}
            </div>
          {% endfor %}
        </div>
      {% endif %}

      {% if progressPosition == 'end' and progress|default %}
        <div class="form__progress">
          {% include '@progress' with {
            current: progress,
          } only %}
        </div>
      {% endif %}
    </form>
  {% endif %}

  {% if not showForm and submitActionMessagePosition == 'bottom-form' and submitActionMessage|default %}
    <div class="form__alert form__alert--success">
      {% include '@alert' with {
        type: 'success',
        text: submitActionMessage,
      } only %}
    </div>
  {% endif %}
</div>
{
  "title": "Das ist ein Formular",
  "pages": [
    {
      "title": "Erste Seite",
      "fields": [
        [
          {
            "label": "Text-Feld",
            "instructions": "Das ist eine Beschreibung",
            "required": true,
            "type": "text",
            "name": "text-field",
            "control": {
              "use": "@input",
              "type": "text"
            }
          }
        ]
      ],
      "buttons": [
        {
          "action": "submit",
          "text": "Absenden"
        }
      ]
    },
    {
      "title": "Zweite Seite",
      "hidden": true,
      "fields": [
        [
          {
            "label": "Text-Feld",
            "instructions": "Das ist eine Beschreibung",
            "required": true,
            "type": "text",
            "name": "text-field",
            "control": {
              "use": "@input",
              "type": "text"
            }
          }
        ]
      ],
      "buttons": [
        {
          "action": "submit",
          "text": "Absenden"
        }
      ]
    }
  ],
  "progress": 50,
  "progressPosition": "start",
  "showTabs": true
}
  • Content:
    $form-mobile-switch-breakpoint: m;
    
    :root {
      --form-alert-margin-block: 4rem;
      --form-errors-background-color: var(--error-color);
      --form-errors-color: var(--color-white);
      --form-errors-font-size: 1.4rem;
      --form-errors-margin-block: 0.7rem;
      --form-errors-padding-block: 0.8rem;
      --form-errors-padding-inline: 1.2rem;
      --form-pages-gap: 3rem;
      --form-page-background-color: var(--color-white);
      --form-page-border-color: var(--color-cyan-light);
      --form-page-border-width: 3px;
      --form-buttons-gap: 4rem;
      --form-buttons-margin-block: 4rem;
      --form-page-fields-column-gap: var(--gap);
      --form-page-fields-row-gap: 2rem;
      --form-page-padding-block: 2rem;
      --form-page-padding-inline: 2rem;
      --form-page-title-color: var(--text-color);
      --form-page-title-font-size: 2rem;
      --form-page-title-font-weight: var(--font-weight-bold);
      --form-page-title-margin-block: 3rem;
      --form-progress-gap: 3rem;
      --form-tab-color: var(--text-color);
      --form-tab-current-font-weight: var(--font-weight-bold);
      --form-tab-font-size: 1.8rem;
      --form-tab-font-weight: var(--font-weight-regular);
      --form-tab-gap: 1rem;
      --form-tab-padding-block: 1.5rem;
      --form-tab-padding-inline: 2rem;
      --form-title-gap: 3rem;
    }
    
    .form {
      padding-inline: var(--form-padding-inline, 0);
    }
    
    .form,
    .form__form,
    .form__page-fields {
      > :first-child {
        margin-block-start: 0;
      }
    
      > :last-child {
        margin-block-end: 0;
      }
    }
    
    .form__alert {
      margin-block: var(--form-alert-margin-block);
    }
    
    .form__title {
      margin-block-end: var(--form-title-gap);
    }
    
    .form__intro-text {
      margin-block-end: var(--form-intro-text-gap, 3rem);
    
      > * + * {
        margin-block-start: 0.5lh;
      }
    }
    
    .form__progress {
      margin-block: var(--form-progress-gap);
    }
    
    .form__errors {
      --notice-color: var(--form-errors-color);
      --notice-icon-color: var(--form-errors-color);
    
      background-color: var(--form-errors-background-color);
      border-radius: var(--border-radius-default);
      font-size: var(--form-errors-font-size);
      margin-block: var(--form-errors-margin-block);
      padding-block: var(--form-errors-padding-block);
      padding-inline: var(--form-errors-padding-inline);
    }
    
    .form__tabs {
      display: flex;
      gap: var(--form-tab-gap);
      margin-block-end: calc(var(--form-page-border-width) * -1);
      position: relative;
      z-index: 2;
    
      @include mq($until: $form-mobile-switch-breakpoint) {
        display: none;
      }
    }
    
    .form__tab {
      background-color: var(--form-page-border-color);
      border: var(--form-page-border-width) solid var(--form-page-border-color);
      border-block-end: 0;
      color: var(--form-tab-color);
      display: block;
      font-size: var(--form-tab-font-size);
      font-weight: var(--form-tab-font-weight);
      padding-block-end: calc(var(--form-tab-padding-block) + var(--form-page-border-width));
      padding-block-start: var(--form-tab-padding-block);
      padding-inline: var(--form-tab-padding-inline);
    
      &[data-conditionally-hidden='true'] {
        display: none;
      }
    }
    
    .form__tab--current {
      background-color: var(--form-page-background-color);
      font-weight: var(--form-tab-current-font-weight);
    }
    
    .form__page {
      & + & {
        margin-block-start: var(--form-pages-gap);
      }
    }
    
    .form__page-title {
      background-color: var(--form-page-border-color);
      border: var(--form-page-border-width) solid var(--form-page-border-color);
      color: var(--form-page-title-color);
      font-size: var(--form-page-title-font-size);
      font-weight: var(--form-page-title-font-weight);
      padding-block: var(--form-page-padding-block);
      padding-inline: var(--form-page-padding-inline);
      position: relative;
      z-index: 2;
    
      .form__page--current & {
        background-color: var(--form-page-background-color);
        border-block-end-width: 1px;
        margin-block-end: calc(var(--form-page-border-width) * -1);
      }
    
      @include mq($from: $form-mobile-switch-breakpoint) {
        display: none;
      }
    }
    
    .form__page-fields {
      appearance: none;
      background-color: var(--form-page-background-color);
      border: var(--form-page-border-width) solid var(--form-page-border-color);
      display: block;
      padding-block: var(--form-page-padding-block);
      padding-inline: var(--form-page-padding-inline);
      position: relative;
      z-index: 1;
    }
    
    .form__page-legend {
      appearance: none;
      color: var(--form-page-title-color);
      display: block;
      float: left;
      font-size: var(--form-page-title-font-size);
      font-weight: var(--form-page-title-font-weight);
      inline-size: 100%;
      margin-block: var(--form-page-title-margin-block);
      padding-inline: 0;
    
      @include use-clearfix();
    
      @include mq($until: $form-mobile-switch-breakpoint) {
        display: none;
      }
    }
    
    .form__page-legend--hidden {
      @include mq($from: $form-mobile-switch-breakpoint) {
        @include use-hidden-visually();
      }
    }
    
    .form__page-fields--hidden {
      display: none;
    }
    
    .form__row {
      --field-groups-column-gap: var(--form-page-fields-column-gap);
      --field-groups-row-gap: var(--form-page-fields-row-gap);
    
      clear: both;
      display: grid;
      gap: var(--form-page-fields-column-gap);
      grid-auto-columns: 1fr;
      grid-auto-flow: column;
    
      & + & {
        margin-block-start: var(--form-page-fields-row-gap);
      }
    
      &[hidden] {
        display: none;
      }
    }
    
    .form__field {
      &[data-conditionally-hidden='true'] {
        display: none;
      }
    }
    
    .form__buttons {
      align-items: center;
      display: flex;
      gap: var(--form-buttons-gap);
      margin-block: var(--form-buttons-margin-block);
    }
    
    .form__buttons--right {
      justify-content: flex-end;
    }
    
    .form__buttons--center-save-right,
    .form__buttons--center-save-left {
      justify-content: center;
    }
    
    .form__button {
      &[data-conditionally-hidden='true'] {
        display: none;
      }
    }
    
    .form__button--save {
      .form__buttons--right-save-left &,
      .form__buttons--center-save-left & {
        order: -2;
      }
    
      .form__buttons--save-right & {
        margin-inline-start: auto;
      }
    
      .form__buttons--save-left & {
        margin-inline-end: auto;
        order: -2;
      }
    }
    
    .form__button--back {
      order: -1;
    }
    
  • URL: /components/raw/form/form.scss
  • Filesystem Path: src/components/3-organisms/form/form.scss
  • Size: 5.9 KB

No notes defined.