diff --git a/src/Plugin/UiPatterns/PropType/SlotPropType.php b/src/Plugin/UiPatterns/PropType/SlotPropType.php
index a6fade789b04ef77c9b9aa02d24fc19d26473fe9..f81853fad2366d9d3d64f1daa6c0cdbc0b35d8e1 100644
--- a/src/Plugin/UiPatterns/PropType/SlotPropType.php
+++ b/src/Plugin/UiPatterns/PropType/SlotPropType.php
@@ -6,6 +6,7 @@ namespace Drupal\ui_patterns\Plugin\UiPatterns\PropType;
 
 use Drupal\Component\Render\MarkupInterface;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Render\Markup;
 use Drupal\Core\Render\RenderableInterface;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\ui_patterns\Attribute\PropType;
@@ -33,44 +34,36 @@ class SlotPropType extends PropTypePluginBase {
       return self::convertObject($value);
     }
     if (is_string($value)) {
-      return ['#markup' => $value];
+      return Markup::create($value);
     }
-    if (is_array($value) && self::isMappingNotRenderable($value)) {
+    if (is_array($value) && empty(Element::properties($value))) {
       // Twig `is sequence` and `is mapping `tests are not useful when a list
       // of renderables has mapping keys (non consecutive, strings) instead of
       // sequence (integer, consecutive) keys. For example a list of blocks
       // from page layout or layout builder: each block is keyed by its UUID.
       // So, transform this list of renderables to a proper Twig sequence.
-      return array_values($value);
+      $value = array_map(static fn($item) => self::normalize($item), array_is_list($value) ? $value : array_values($value));
+      return (count($value) === 1) ? reset($value) : $value;
     }
     return $value;
   }
 
-  /**
-   * Is the array a mapping array but not a renderable array?
-   */
-  protected static function isMappingNotRenderable(array $value): bool {
-    return count($value) > 1 && !array_is_list($value) && empty(Element::properties($value));
-  }
-
   /**
    * Convert PHP objects to render array.
    */
-  protected static function convertObject(object $value): array {
+  protected static function convertObject(object $value): mixed {
     if ($value instanceof RenderableInterface) {
       $value = $value->toRenderable();
     }
     if ($value instanceof MarkupInterface) {
-      return [
-        '#markup' => (string) $value,
-      ];
+      return $value;
     }
     elseif ($value instanceof \Stringable) {
       return [
         '#plain_text' => (string) $value,
       ];
     }
-    return [];
+    return $value;
   }
 
   /**
diff --git a/tests/modules/ui_patterns_test/components/test-component/test-component.twig b/tests/modules/ui_patterns_test/components/test-component/test-component.twig
index 10ff70a2dafc23a899d899d1637b6f1c5dcf2caa..19530d8ec5c47a8b888099ca2569da8ee503e328 100644
--- a/tests/modules/ui_patterns_test/components/test-component/test-component.twig
+++ b/tests/modules/ui_patterns_test/components/test-component/test-component.twig
@@ -1,4 +1,4 @@
-<div{{ attributes.addClass(["ui-patterns-test-component"]) }}>
+<div{{ attributes.addClass(['ui-patterns-test-component']) }}>
   <div class="ui-patterns-props-string">
     {{ string }}
   </div>
diff --git a/tests/modules/ui_patterns_test/components/test-form-component/test-form-component.component.yml b/tests/modules/ui_patterns_test/components/test-form-component/test-form-component.component.yml
new file mode 100644
index 0000000000000000000000000000000000000000..61ff349ea8c2f70f3bbb9ae041064a20c97f206a
--- /dev/null
+++ b/tests/modules/ui_patterns_test/components/test-form-component/test-form-component.component.yml
@@ -0,0 +1,14 @@
+name: "UI Patterns Test wrapper component"
+props:
+  type: object
+  properties:
+    string:
+      title: "String"
+      type: "string"
+    base_id:
+      title: "base id"
+      $ref: "ui-patterns://identifier"
+slots:
+  slot:
+    title: "slot"
+    description: "slot"
diff --git a/tests/modules/ui_patterns_test/components/test-form-component/test-form-component.twig b/tests/modules/ui_patterns_test/components/test-form-component/test-form-component.twig
new file mode 100644
index 0000000000000000000000000000000000000000..cd9040f1d185c2a1203893662a1395166ec78883
--- /dev/null
+++ b/tests/modules/ui_patterns_test/components/test-form-component/test-form-component.twig
@@ -0,0 +1,5 @@
+{% set base_id = base_id|default('ui-patterns-test-form') %}
+<form {{ attributes.addClass(['ui-patterns-test-form', base_id]) }}>
+    <textarea id="{{ base_id }}-textarea">{{ slot }}</textarea>
+    <input   id="{{ base_id }}-input" type="text" name="name" value="{{ string }}" />
+</form>
diff --git a/tests/src/Kernel/SlotNormalizationTest.php b/tests/src/Kernel/SlotNormalizationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a797049a04615a4e805ba2ce0bdf98791263af20
--- /dev/null
+++ b/tests/src/Kernel/SlotNormalizationTest.php
@@ -0,0 +1,104 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\ui_patterns\Kernel;
+
+use Drupal\Core\Render\Markup;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\ui_patterns\Traits\TestDataTrait;
+
+/**
+ * Test slot normalization.
+ *
+ * @group ui_patterns
+ */
+class SlotNormalizationTest extends KernelTestBase {
+
+  use TestDataTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'system',
+    'user',
+    'text',
+    'field',
+    'node',
+    'ui_patterns',
+    'ui_patterns_test',
+    'datetime',
+    'filter',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installSchema('node', 'node_access');
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+    $this->installConfig(['system', 'filter']);
+  }
+
+  /**
+   * Test slot normalization.
+   */
+  public function testSlotNormalization() : void {
+    $tested_values = [
+      ["my slot"],
+      "my slot",
+      Markup::create("my slot"),
+      ["#markup" => "my slot"],
+      ["a" => ["#markup" => "my "], "b" => ["#markup" => "slot"]],
+       ["aa" => "my slot"],
+      t("my slot"),
+      ["#type" => "inline_template", "#template" => "my slot"],
+    ];
+    $render_array_test = [
+      "#type" => "inline_template",
+      "#template" => "{{ include('ui_patterns_test:test-component', {slot: injected}) }}",
+      "#context" => ["injected" => ""],
+    ];
+    foreach ($tested_values as $tested_value) {
+      $this->assertExpectedOutput(
+        [
+          "rendered_value" => "my slot",
+          "assert" => "assertStringContainsString",
+        ],
+        array_merge($render_array_test, ["#context" => ["injected" => $tested_value]])
+      );
+    }
+  }
+
+  /**
+   * Test slot normalization.
+   */
+  public function testNestedComponentWithForm() : void {
+    // Test nested component with form.
+    $render_array_test = [
+      "#type" => "inline_template",
+      "#template" => "
+    {% set comp_form = include('ui_patterns_test:test-form-component', {}) %}
+    {{ include('ui_patterns_test:test-component', {slot: comp_form}) }}",
+      "#context" => [],
+    ];
+    $this->assertExpectedOutput(
+      [
+        "rendered_value" => "<input ",
+        "assert" => "assertStringContainsString",
+      ],
+      $render_array_test
+    );
+    $this->assertExpectedOutput(
+          [
+            "rendered_value" => "<form ",
+            "assert" => "assertStringContainsString",
+          ],
+          $render_array_test
+        );
+  }
+
+}
diff --git a/tests/src/Kernel/TwigVisitorTest.php b/tests/src/Kernel/TwigVisitorTest.php
index e4738078e67bbe5bea700f27228e0d488ad805b0..5f30bb4e561cb0b9e9c4476f985879e038eb506d 100644
--- a/tests/src/Kernel/TwigVisitorTest.php
+++ b/tests/src/Kernel/TwigVisitorTest.php
@@ -8,7 +8,7 @@ use Drupal\KernelTests\KernelTestBase;
 use Drupal\Tests\ui_patterns\Traits\TestDataTrait;
 
 /**
- * Base class to test source plugins.
+ * Test node visitor.
  *
  * @group ui_patterns
  */
@@ -43,9 +43,9 @@ class TwigVisitorTest extends KernelTestBase {
   }
 
   /**
-   * Test attributes.
+   * Test different twig usages.
    */
-  public function testAttributes() : void {
+  public function testTwigIntegration() : void {
 
     $default_context = [
       'prop_string' => $this->randomMachineName(),