<div id="form-31222-20095" class="form">
<form id="form-31222-20095-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__pages">
<div class="form__page form__page--current">
<fieldset class="form__page-fields">
<legend class="form__page-legend form__page-legend--hidden">Form page</legend>
<div class="form__row">
<div id="form-31222-20095-field-43420-25463" class="field form__field">
<label class="field__label" for="form-31222-20095-field-43420-25463-control">
<span class="label">Text-Feld<span aria-hidden="true" class="label__required" title="Notwendig">*</span></span>
</label>
<div id="form-31222-20095-field-43420-25463-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-31222-20095-field-43420-25463-control" name="text-field" required aria-describedby="form-31222-20095-field-43420-25463-instructions" aria-required="true" type="text" />
</div>
</div>
</div>
</div>
<div class="field__footer">
<div class="field__instructions" id="form-31222-20095-field-43420-25463-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": [
{
"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"
}
]
}
]
}
$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;
}
No notes defined.