+
+{% } else if (ctx.component.type === 'form') { %}
+
+ {{ctx.element}}
+
+
{% } else { %}
{% } %}
diff --git a/src/formio/templates/fieldset.ejs b/src/formio/templates/fieldset.ejs
index eb7902216..30dcd32e5 100644
--- a/src/formio/templates/fieldset.ejs
+++ b/src/formio/templates/fieldset.ejs
@@ -8,7 +8,7 @@
{% } %}
{% if (!ctx.collapsed) { %}
-
+
{{ctx.children}}
{% } %}
diff --git a/src/scss/components/_deprecated-select.scss b/src/scss/components/_deprecated-select.scss
index 84e3d97be..bbd6efaf2 100644
--- a/src/scss/components/_deprecated-select.scss
+++ b/src/scss/components/_deprecated-select.scss
@@ -11,6 +11,7 @@ $select-background-color: var(--of-select-background-color, $color-white);
// Styling for the choicejs widget for the select component
// Overwriting styles found here: https://github.com/Choices-js/Choices/blob/master/src/styles/choices.scss
+// FIXME: check impact of form-control removal
.#{prefix(form-control--select)} {
$control-height: $grid-row-height;
$list-hpadding: $grid-margin-2;
diff --git a/src/scss/components/_file-upload.scss b/src/scss/components/_file-upload.scss
index 5ea2aa93c..3644bd5ed 100644
--- a/src/scss/components/_file-upload.scss
+++ b/src/scss/components/_file-upload.scss
@@ -11,6 +11,7 @@ we don't have strict BEM naming here.
@import '../mixins/prefix';
@import '../mixins/bootstrap';
+// FIXME: these class names are gone -> find different selector
.#{prefix(form-control--file)} {
@include body;
@include anchor.extend-utrecht-link;
diff --git a/src/scss/components/_form-control.scss b/src/scss/components/_form-control.scss
deleted file mode 100644
index c53d5ed76..000000000
--- a/src/scss/components/_form-control.scss
+++ /dev/null
@@ -1,94 +0,0 @@
-@use 'microscope-sass/lib/bem';
-
-@import '~microscope-sass/lib/typography';
-
-@import '../mixins/prefix';
-
-.#{prefix(form-control)} {
- position: relative;
-
- // add vertical space/padding on top for elements except the first child in a container
- // This is sort of the inverse of @include margin(auto) which operates on the last-child.
- &:not(:first-child) {
- @include responsive(
- $properties: padding-top,
- $value-mobile: $grid-margin-3,
- $value-tablet: $grid-margin-4
- );
- }
-
- @include bem.modifier('hidden') {
- display: none;
- }
-
- &.error {
- @include border(left, var(--of-color-danger), 4px);
- padding-left: $grid-margin-3;
- }
-
- &.warning {
- @include border(left, var(--of-color-warning), 4px);
- padding-left: $grid-margin-3;
- }
-
- &.success {
- @include border(left, var(--of-color-success), 4px);
- padding-left: $grid-margin-3;
- }
-
- &.info {
- @include border(left, var(--of-color-info), 4px);
- padding-left: $grid-margin-3;
- }
-
- &.formio-error-wrapper,
- &.has-error {
- @include border(left, var(--of-color-danger), 4px);
- padding: $grid-margin-3;
- background-color: var(--of-alert-error-bg);
- }
-
- .#{prefix(prefix)} {
- @include margin($value-mobile: $typography-margin-list);
- }
-
- .#{prefix(body)},
- .#{prefix(suffix)} {
- @include margin(true, margin-top, $value-mobile: $typography-margin-list);
- }
-
- .#{prefix(body)} {
- display: block;
-
- &--inline {
- display: inline-block;
- margin-block-start: 0;
- }
- }
-
- &--no-asterisks {
- .required-field:after,
- .utrecht-form-label.utrecht-form-label--openforms-required:after {
- // Override the asterisk
- content: '' !important;
- }
- }
-
- .group {
- display: flex;
- align-items: center;
- }
-
- // Overwriting Formio style
- .control-label--hidden {
- position: static !important;
- }
-
- &--editgrid {
- & > label {
- // Only the label of the whole repeating group has h3 style. Not the label of each field
- // within a repeat of the group.
- @include h3;
- }
- }
-}
diff --git a/src/scss/components/_form-field-container.scss b/src/scss/components/_form-field-container.scss
new file mode 100644
index 000000000..662d26b48
--- /dev/null
+++ b/src/scss/components/_form-field-container.scss
@@ -0,0 +1,23 @@
+@use 'microscope-sass/lib/bem';
+
+/**
+ * NL DS is discussing spacing between form fields, for the time being we need to
+ * solve this ourselves.
+ *
+ * The canonical component for this is "openforms-form-field-container", but note that
+ * we also target some other classes to share these styles because of formio reasons.
+ *
+ * This is the path of least resistance to achieve our goals and rip out form-control
+ * components.
+ */
+.openforms-form-field-container {
+ display: flex;
+ flex-direction: column;
+ gap: var(--of-form-field-container-gap, 24px); // 24px fallback for backwards compatibilty
+}
+
+// class set on the top-level formio form which renders its 'components' (
+// ``configuration.components`` in JSON)
+.formio-form {
+ @extend .openforms-form-field-container;
+}
diff --git a/src/scss/components/_form-field.scss b/src/scss/components/_form-field.scss
index 8178481ca..ee030dc04 100644
--- a/src/scss/components/_form-field.scss
+++ b/src/scss/components/_form-field.scss
@@ -1,7 +1,5 @@
@use 'microscope-sass/lib/bem';
-@import '@utrecht/components/dist/form-field/css/index.css';
-
// Overrides of the utrecht form field styles for our own theme
.openforms-theme {
.utrecht-form-field {
diff --git a/src/scss/components/_formio-component.scss b/src/scss/components/_formio-component.scss
new file mode 100644
index 000000000..0eb7c16ff
--- /dev/null
+++ b/src/scss/components/_formio-component.scss
@@ -0,0 +1,55 @@
+@use 'microscope-sass/lib/bem';
+@use '@utrecht/components/form-field/css/mixin' as form-field;
+@use '@utrecht/components/form-fieldset/css/mixin' as form-fieldset;
+
+@import '~microscope-sass/lib/typography';
+
+@import '../mixins/prefix';
+
+// These styles are required because form.io doesn't re-render with new classnames,
+// instead it looks up the component ref and then adds the validation error classnames.
+// The (direct) child inside this node are the utrecht components that need to gain
+// the validation-error styles, so we use sass extend and include to achieve that.
+[ref='component'] {
+ &.has-error,
+ &.formio-error-wrapper {
+ > .utrecht-form-field {
+ @extend .utrecht-form-field--invalid;
+ @include form-field.utrecht-form-field--invalid;
+ }
+
+ > .utrecht-form-fieldset {
+ @extend .utrecht-form-fieldset--invalid;
+ @include form-fieldset.utrecht-form-fieldset--invalid;
+ }
+ }
+}
+
+.#{prefix(form-control)} {
+ .#{prefix(body)} {
+ display: block;
+
+ &--inline {
+ display: inline-block;
+ margin-block-start: 0;
+ }
+ }
+
+ &--no-asterisks {
+ .required-field:after,
+ .utrecht-form-label.utrecht-form-label--openforms-required:after {
+ // Override the asterisk
+ content: '' !important;
+ }
+ }
+
+ .group {
+ display: flex;
+ align-items: center;
+ }
+
+ // Overwriting Formio style
+ .control-label--hidden {
+ position: static !important;
+ }
+}
diff --git a/src/scss/nl-design-system-community.scss b/src/scss/nl-design-system-community.scss
index f85c20328..086e764ae 100644
--- a/src/scss/nl-design-system-community.scss
+++ b/src/scss/nl-design-system-community.scss
@@ -1,5 +1,6 @@
@import '@utrecht/components/dist/document/css/index.css';
@import '@utrecht/components/dist/img/css/index.css';
@import '@utrecht/components/dist/paragraph/css/index.css';
+@import '@utrecht/components/dist/form-field/css/index.css';
@import '@utrecht/components/dist/form-fieldset/css/index.css';
@import '@utrecht/components/dist/radio-button/css/index.css';
diff --git a/src/styles.scss b/src/styles.scss
index 12d60dbf3..1bc9e1e28 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -27,10 +27,11 @@
@import './scss/components/card';
@import './scss/components/content';
@import './scss/components/errors';
-@import './scss/components/form-control';
+@import './scss/components/formio-component';
@import './scss/components/help-text';
@import './scss/components/image';
@import './scss/components/form-field';
+@import './scss/components/form-field-container';
@import './scss/components/radio-field'; // must come after form-field due to some OF-specific overrides
@import './scss/components/input';
@import './scss/components/label';