diff --git a/modules/ui_patterns_field/src/Plugin/Derivative/UIPatternsSourceFieldPropertySourceDeriver.php b/modules/ui_patterns_field/src/Plugin/Derivative/UIPatternsSourceFieldPropertySourceDeriver.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb9d6709130f2732445bf5f698a726b6671f15fb
--- /dev/null
+++ b/modules/ui_patterns_field/src/Plugin/Derivative/UIPatternsSourceFieldPropertySourceDeriver.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\ui_patterns_field\Plugin\Derivative;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\ui_patterns\Plugin\Derivative\EntityFieldSourceDeriverBase;
+
+/**
+ * Provides Plugin for every field property of type ui_patterns_source.
+ */
+class UIPatternsSourceFieldPropertySourceDeriver extends EntityFieldSourceDeriverBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDerivativeDefinitionsForEntityStorageField(string $entity_type_id, string $field_name, array $base_plugin_derivative): void {
+    $id = implode(PluginBase::DERIVATIVE_SEPARATOR, [
+      $entity_type_id,
+      $field_name,
+    ]);
+    $field_type = $this->entityFieldsMetadata[$entity_type_id]["field_storages"][$field_name]["metadata"]["type"];
+    if ($field_type === "ui_patterns_source") {
+      $this->derivatives[$id] = array_merge(
+        $base_plugin_derivative,
+        [
+          "id" => $id,
+          "tags" => array_merge($base_plugin_derivative["tags"], ["ui_patterns_source"]),
+        ]);
+      $field_storage_data = $this->entityFieldsMetadata[$entity_type_id]["field_storages"][$field_name];
+      $bundle_context_for_properties = (new ContextDefinition('string'))
+        ->setRequired()
+        ->setLabel("Bundle")
+        ->addConstraint('AllowedValues', array_merge($field_storage_data["bundles"] ?? [], [""]));
+      $this->derivatives[$id]["context_definitions"]["bundle"] = $bundle_context_for_properties;
+    }
+
+  }
+
+}
diff --git a/modules/ui_patterns_field/src/Plugin/Field/FieldType/SourceValueItem.php b/modules/ui_patterns_field/src/Plugin/Field/FieldType/SourceValueItem.php
new file mode 100644
index 0000000000000000000000000000000000000000..315b3cfafb397cfb9ef695adf71bea3db2788934
--- /dev/null
+++ b/modules/ui_patterns_field/src/Plugin/Field/FieldType/SourceValueItem.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\ui_patterns_field\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\Attribute\FieldType;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\MapFieldItemList;
+use Drupal\Core\Field\Plugin\Field\FieldType\MapItem;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Field Type to store UI Patterns source configuration.
+ *
+ * @property string $source_id
+ * @property string $source
+ */
+#[FieldType(
+  id: "ui_patterns_source",
+  label: new TranslatableMarkup("Source (UI Patterns)"),
+  description: new TranslatableMarkup("Store an UI Patterns source configuration"),
+  default_widget: "ui_patterns_source",
+  default_formatter: "ui_patterns_source",
+  list_class: MapFieldItemList::class,
+)]
+class SourceValueItem extends MapItem {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function mainPropertyName() {
+    return 'source_id';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    return [
+      'columns' => [
+        'source_id' => [
+          'type' => 'varchar_ascii',
+          'length' => 255,
+
+        ],
+        'source' => [
+          'type' => 'blob',
+          'size' => 'big',
+          'serialize' => TRUE,
+        ],
+      ],
+    ];
+  }
+
+}
diff --git a/modules/ui_patterns_field/src/Plugin/Field/FieldWidget/SourceComponentWidget.php b/modules/ui_patterns_field/src/Plugin/Field/FieldWidget/SourceComponentWidget.php
new file mode 100644
index 0000000000000000000000000000000000000000..04989affeee3e0a2f2ee9262491ea24557edaf08
--- /dev/null
+++ b/modules/ui_patterns_field/src/Plugin/Field/FieldWidget/SourceComponentWidget.php
@@ -0,0 +1,331 @@
+<?php
+
+namespace Drupal\ui_patterns_field\Plugin\Field\FieldWidget;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Field\Attribute\FieldWidget;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\Theme\ComponentPluginManager;
+use Drupal\ui_patterns\Form\ComponentFormBuilderTrait;
+use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\ui_patterns\ComponentPluginManager as UIPatternsComponentPluginManager;
+
+/**
+ * A widget to display the UI Patterns configuration form.
+ *
+ * @internal
+ *   Plugin classes are internal.
+ */
+#[FieldWidget(
+  id: 'ui_patterns_source_component',
+  label: new TranslatableMarkup('Components only (UI Patterns)'),
+  description: new TranslatableMarkup('Widget to edit an UI Patterns source field, but configure only the Component source for a slot.'),
+  field_types: ['ui_patterns_source'],
+)]
+class SourceComponentWidget extends WidgetBase {
+
+  use ComponentFormBuilderTrait;
+
+  /**
+   * The component plugin manager.
+   *
+   * @var \Drupal\Core\Theme\ComponentPluginManager
+   */
+  protected ComponentPluginManager $componentPluginManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $instance->componentPluginManager = $container->get('plugin.manager.sdc');
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return [
+      'component_id' => NULL,
+      'hide_slots' => TRUE,
+      'prop_sources' => NULL,
+      'prop_filter_enable' => FALSE,
+      'selection' => [],
+    ] + parent::defaultSettings();
+  }
+
+  /**
+   * Get the widget settings.
+   *
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   Form state.
+   *
+   * @return array
+   *   Widget settings.
+   */
+  protected function getWidgetSettings(FormStateInterface $form_state) : array {
+    $field_name = $this->fieldDefinition->getName();
+    $array_parents = ["fields", $field_name, "settings_edit_form", "settings"];
+    $full_form_state_values = $form_state->getValues();
+    $current_settings = &NestedArray::getValue($full_form_state_values, $array_parents);
+    return array_merge($this->getSettings(), $current_settings ?? []);
+  }
+
+  /**
+   * Get the component options.
+   *
+   * @return array
+   *   Component options.
+   */
+  protected function getComponentOptions() : array {
+    $definitions = [];
+    if ($this->componentPluginManager instanceof UIPatternsComponentPluginManager) {
+      $definitions = $this->componentPluginManager->getGroupedDefinitions();
+    }
+    $options = [];
+    foreach ($definitions as $group_id => $group) {
+      foreach ($group as $component_id => $definition) {
+        $options[$group_id][$component_id] = $definition['annotated_name'];
+      }
+    }
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $options = $this->getComponentOptions();
+    $field_name = $this->fieldDefinition->getName();
+    $settings = $this->getWidgetSettings($form_state);
+
+    $wrapper_id = 'component-props-selection';
+    $element = [];
+    $element['component_id'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Component ID'),
+      '#default_value' => $this->getSetting('component_id'),
+      '#required' => FALSE,
+      '#options' => $options,
+      '#ajax' => [
+        'callback' => [static::class, 'changeSelectorFormChangeAjax'],
+        'wrapper' => $wrapper_id,
+        'effect' => 'fade',
+      ],
+      '#executes_submit_callback' => FALSE,
+      '#empty_value' => '',
+      '#empty_option' => t('- None -'),
+    ];
+    $element['hide_slots'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Hide slots'),
+      '#default_value' => $settings['hide_slots'] ?? TRUE,
+      '#required' => FALSE,
+    ];
+    $prop_sources = $settings['prop_sources'] ?? NULL;
+    if ($prop_sources === NULL) {
+      $prop_sources = '';
+    }
+    $element['prop_sources'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Prop sources'),
+      '#options' => [
+        '' => $this->t('Display all'),
+        'widgets' => $this->t('Only widgets'),
+        'default' => $this->t('Only default'),
+      ],
+      '#default_value' => $prop_sources,
+      '#required' => FALSE,
+    ];
+    $element['prop_filter_enable'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Show only selected props'),
+      '#default_value' => $settings['prop_filter_enable'] ?? FALSE,
+      '#required' => FALSE,
+      '#states' => [
+        'visible' => [
+          [
+            ":input[name='fields[{$field_name}][settings_edit_form][settings][component_id]']" => ['!value' => ''],
+          ],
+        ],
+      ],
+    ];
+
+    $element["selection"] = [
+      "#type" => "container",
+      "#attributes" => [
+        "id" => $wrapper_id,
+      ],
+      "#tree" => TRUE,
+
+    ];
+    $component_id_selected = $settings["component_id"] ?? '';
+    if (!empty($component_id_selected)) {
+      $selection = $settings["selection"] ?? [];
+      try {
+        $component_selected = $this->componentPluginManager->find($component_id_selected);
+        $props = $component_selected->metadata->schema['properties'];
+        $options = ["variant" => t("Variant")];
+        foreach ($props as $prop_id => $prop) {
+          if ($prop_id === 'variant') {
+            continue;
+          }
+          $propTitle = $prop['title'] ?? '';
+          $options[$prop_id] = empty($propTitle) ? $prop_id : $propTitle;
+        }
+        $element["selection"]['prop_filter'] = [
+          "#type" => "select",
+          '#limit_validation_errors' => [],
+          "#multiple" => TRUE,
+          "#options" => $options,
+          "#default_value" => $selection['prop_filter'] ?? [],
+          '#states' => [
+            'visible' => [
+              [
+                ":input[name='fields[{$field_name}][settings_edit_form][settings][prop_filter_enable]']" => ['checked' => TRUE],
+                ":input[name='fields[{$field_name}][settings_edit_form][settings][component_id]']" => ['!value' => ''],
+              ],
+            ],
+          ],
+        ];
+      }
+      catch (ComponentNotFoundException $e) {
+
+      }
+    }
+    return $element;
+  }
+
+  /**
+   * Ajax callback for component selector change.
+   */
+  public static function changeSelectorFormChangeAjax(
+    array $form,
+    FormStateInterface $form_state,
+  ) : array {
+    $parents = $form_state->getTriggeringElement()['#array_parents'];
+    $sub_form_parents = array_merge(array_slice($parents, 0, -1), ["selection"]);
+    $sub_form = NestedArray::getValue($form, $sub_form_parents);
+    $form_state->setRebuild();
+    return $sub_form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = [];
+    if ($this->getSetting('component_id') !== NULL) {
+      $summary[] = $this->t('Component Id: @component', ['@component' => $this->getSetting('component_id')]);
+    }
+    if (!($this->getSetting('hide_slots') ?? TRUE)) {
+      $summary[] = $this->t('Hide slots');
+    }
+    $selection = $this->getSetting('prop_filter_enable') ?? [];
+    $props_selection = $selection['props'] ?? NULL;
+    if (is_array($props_selection)) {
+      $summary[] = $this->t('Only selected props: @props', ['@props' => implode(",", $props_selection)]);
+    }
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
+    $field_name = $this->fieldDefinition->getName();
+    $parents = $form['#parents'];
+    if (!static::getWidgetState($parents, $field_name, $form_state)) {
+      $field_state = [
+        'items_count' => count($items) - 1,
+        'array_parents' => [],
+      ];
+      static::setWidgetState($parents, $field_name, $form_state, $field_state);
+    }
+    return parent::form($items, $form, $form_state, $get_delta);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $item_delta_value = $items[$delta]->getValue() ?? [];
+    $source_id = $item_delta_value['source_id'] ?? 'component';
+    $field_name = $this->fieldDefinition->getName();
+    $element['#parents'] = array_merge($element['#field_parents'] ?? [], [$field_name, $delta]);
+    $settings = $this->getSettings() ?? [];
+    $component_id = $settings['component_id'] ?? NULL;
+    if (empty($component_id)) {
+      $component_id = NULL;
+    }
+    if ($source_id !== 'component') {
+      // The widget can only deal with component sources.
+      // To make sure no data will be overwritten we disable the widget.
+      $element['#access'] = FALSE;
+      return $element;
+    }
+    $source_data = $item_delta_value["source"] ?? [];
+    $component_default_value = $source_data['component'] ?? [];
+    $component_in_data = $component_default_value['component_id'] ?? NULL;
+    if (!isset($component_default_value['component_id'])) {
+      $component_default_value['component_id'] = $component_id;
+    }
+    elseif ($component_id && $component_in_data && $component_in_data !== $component_id) {
+      $element['#access'] = FALSE;
+      return $element;
+    }
+    $contexts = $this->getComponentSourceContexts($items);
+    $element['source'] = [
+      '#type' => 'container',
+      '#tree' => TRUE,
+    ];
+    $selection = $settings["selection"] ?? [];
+    $prop_sources = $settings['prop_sources'] ?? '';
+    $wrap = ($prop_sources !== 'default');
+    $hide_slots = $settings['hide_slots'] ?? TRUE;
+    $element['source']["component"] = array_merge(
+      $this->buildComponentsForm($form_state, $contexts, $component_id),
+      [
+        '#render_slots' => !$hide_slots,
+        '#tag_filter' => ((bool) ($settings['only_widgets'] ?? TRUE)) ? ["widget" => TRUE] : [],
+        '#default_value' => $component_default_value,
+        '#wrap' => $wrap,
+        '#render_headings' => !$hide_slots,
+        '#render_sources' => $wrap,
+        '#prop_filter' => ($this->getSetting('prop_filter_enable') ?? FALSE) ? $selection['prop_filter'] ?? NULL : NULL,
+      ]
+    );
+    $element['source_id'] = ['#type' => 'hidden', '#value' => $source_id];
+    return $element;
+  }
+
+  /**
+   * Set the context.
+   *
+   * @param \Drupal\Core\Field\FieldItemListInterface|null $items
+   *   Field items.
+   *
+   * @return array
+   *   Source contexts.
+   */
+  protected function getComponentSourceContexts(?FieldItemListInterface $items = NULL): array {
+    $contexts = [];
+    if ($entity = $items?->getEntity()) {
+      $contexts['entity'] = EntityContext::fromEntity($entity);
+      $contexts['bundle'] = new Context(ContextDefinition::create('string'), $contexts["entity"]->getContextValue()->bundle() ?? "");
+    }
+    $contexts = RequirementsContext::addToContext(["field_granularity:item"], $contexts);
+    return $contexts;
+  }
+
+}
diff --git a/modules/ui_patterns_field/src/Plugin/Field/FieldWidget/SourceWidget.php b/modules/ui_patterns_field/src/Plugin/Field/FieldWidget/SourceWidget.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1bad2856514f020e4e13190e3e47095371eaf86
--- /dev/null
+++ b/modules/ui_patterns_field/src/Plugin/Field/FieldWidget/SourceWidget.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace Drupal\ui_patterns_field\Plugin\Field\FieldWidget;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Field\Attribute\FieldWidget;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\ui_patterns\Element\ComponentSlotForm;
+use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
+use Drupal\ui_patterns\SourcePluginManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * A widget to display the UI Patterns configuration form.
+ *
+ * @internal
+ *   Plugin classes are internal.
+ */
+#[FieldWidget(
+  id: 'ui_patterns_source',
+  label: new TranslatableMarkup('All slot sources (UI Patterns)'),
+  description: new TranslatableMarkup('Widget to edit an UI Patterns source field and configure any source for a slot.'),
+  field_types: ['ui_patterns_source'],
+)]
+class SourceWidget extends WidgetBase {
+
+  /**
+   * The source plugin manager.
+   *
+   * @var \Drupal\ui_patterns\SourcePluginManager
+   */
+  protected SourcePluginManager $sourcePluginManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $instance->sourcePluginManager = $container->get('plugin.manager.ui_patterns_source');
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $field_name = $this->fieldDefinition->getName();
+    $element['#slot_id'] = $delta;
+    $element['#parents'] = array_merge($element['#field_parents'] ?? [], [$field_name, $delta]);
+    $default_value = $this->getDefaultValue($items, $delta, $element, $form, $form_state);
+    $element['#source_contexts'] = $this->getComponentSourceContexts($items);
+    $element['#tag_filter'] = $this->getSetting('tag_filter') ?? [];
+    $source_form = ComponentSlotForm::buildSourceForm($element, $form_state, [], $default_value);
+    $source_form['source_id']['#empty_option'] = t("- Select a source to add -");
+    return $element + $source_form;
+  }
+
+  /**
+   * Returns the default value for the source field.
+   *
+   * @param \Drupal\Core\Field\FieldItemListInterface $items
+   *   The field items.
+   * @param int $delta
+   *   The delta.
+   * @param array $element
+   *   The element.
+   * @param array $form
+   *   The form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   *
+   * @return mixed
+   *   The default value.
+   *
+   * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+   */
+  protected function getDefaultValue(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) : mixed {
+    $full_form_state_values = $form_state->getValues() ?? [];
+    $full_input = $form_state->getUserInput();
+    $form_state_values = &NestedArray::getValue($full_form_state_values, $element["#parents"] ?? []);
+    if (!empty($full_input) || $form_state->isProcessingInput() || $form_state->isRebuilding()) {
+      $form_state_values = &NestedArray::getValue($full_input, $element["#parents"] ?? []);
+    }
+    $default_value = array_merge($items[$delta]?->getValue() ?? [], $form_state_values ?? []);
+    return $default_value;
+  }
+
+  /**
+   * Set the context.
+   *
+   * @param \Drupal\Core\Field\FieldItemListInterface|null $items
+   *   Field items.
+   *
+   * @return array
+   *   Source contexts.
+   */
+  protected function getComponentSourceContexts(?FieldItemListInterface $items = NULL): array {
+    $contexts = [];
+    if ($entity = $items?->getEntity()) {
+      $contexts['entity'] = EntityContext::fromEntity($entity);
+      $contexts['bundle'] = new Context(ContextDefinition::create('string'), $contexts["entity"]->getContextValue()->bundle() ?? "");
+    }
+    $contexts = RequirementsContext::addToContext(["field_granularity:item"], $contexts);
+    return $contexts;
+  }
+
+}
diff --git a/modules/ui_patterns_field/src/Plugin/UiPatterns/Source/UIPatternsSourceFieldPropertySource.php b/modules/ui_patterns_field/src/Plugin/UiPatterns/Source/UIPatternsSourceFieldPropertySource.php
new file mode 100644
index 0000000000000000000000000000000000000000..d11f95d8b3f024c65e77fd2ab84b9272231da505
--- /dev/null
+++ b/modules/ui_patterns_field/src/Plugin/UiPatterns/Source/UIPatternsSourceFieldPropertySource.php
@@ -0,0 +1,121 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\ui_patterns_field\Plugin\UiPatterns\Source;
+
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\ui_patterns\Attribute\Source;
+use Drupal\ui_patterns\Plugin\UiPatterns\Source\FieldPropertySource;
+use Drupal\ui_patterns_field\Plugin\Derivative\UIPatternsSourceFieldPropertySourceDeriver;
+use Drupal\ui_patterns_field\Plugin\Field\FieldType\SourceValueItem;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the prop source.
+ */
+#[Source(
+  id: 'ui_patterns_source',
+  label: new TranslatableMarkup('Value from the component in field.'),
+  description: new TranslatableMarkup('Map the prop/slot value to the one configured in the component stored the "Source" field.'),
+  deriver: UIPatternsSourceFieldPropertySourceDeriver::class
+)]
+class UIPatternsSourceFieldPropertySource extends FieldPropertySource {
+
+  /**
+   * The component element builder.
+   *
+   * @var \Drupal\ui_patterns\Element\ComponentElementBuilder
+   */
+  protected $componentElementBuilder;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(
+    ContainerInterface $container,
+    array $configuration,
+    $plugin_id,
+    $plugin_definition,
+  ) {
+    // We keep the same constructor as SourcePluginBase.
+    $instance = parent::create(
+      $container,
+      $configuration,
+      $plugin_id,
+      $plugin_definition
+    );
+    // Defined in parent class FieldSourceBase.
+    $instance->componentElementBuilder = $container->get('ui_patterns.component_element_builder');
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPropValue(): mixed {
+    $items = $this->getEntityFieldItemList();
+    $delta = (isset($this->context['ui_patterns:field:index'])) ? $this->getContextValue('ui_patterns:field:index') : 0;
+    if (empty($items)) {
+      return NULL;
+    }
+    /** @var \Drupal\Core\Field\FieldItemInterface $field_item_at_delta */
+    $field_item_at_delta = $items->get($delta);
+    if (!$field_item_at_delta || !($field_item_at_delta instanceof SourceValueItem)) {
+      return NULL;
+    }
+    $source_id = $field_item_at_delta->source_id ?? 'component';
+    if ($source_id !== 'component') {
+      return NULL;
+    }
+    $source_configuration = $field_item_at_delta->source ?? [];
+    if (!is_array($source_configuration)) {
+      $source_configuration = [];
+    }
+    return $this->extractComponentPropValue($source_configuration);
+  }
+
+  /**
+   * Extract the prop value from the source configuration.
+   *
+   * @param array $source_configuration
+   *   The source configuration.
+   *
+   * @return mixed
+   *   The prop value.
+   */
+  protected function extractComponentPropValue(array $source_configuration) : mixed {
+    $component_configuration = $source_configuration['component'] ?? [];
+    // $component_id = $component_configuration['component_id'] ?? NULL;
+    $propDefinition = $this->getPropDefinition();
+    $propId = $this->getPropId();
+    /** @var \Drupal\ui_patterns\PropTypeInterface $propType */
+    $propType = $propDefinition["ui_patterns"]["type_definition"];
+    $contexts = $this->getContexts();
+    $build = [];
+    if ($propType->getPluginId() === "slot") {
+      $sources = $component_configuration['slots'][$propId]["sources"] ?? [];
+      foreach ($sources as $source) {
+        $build = $this->componentElementBuilder->buildSource($build, $propId, $propDefinition, $source, $contexts);
+      }
+      return $build['#slots'][$propId] ?? [];
+    }
+    $build = [];
+    $prop_source_config = (($propId === "variant") && !empty($component_configuration["variant_id"])) ? $component_configuration["variant_id"] : ($component_configuration['props'][$propId] ?? []);
+    if (empty($prop_source_config)) {
+      return NULL;
+    }
+    $build = $this->componentElementBuilder->buildSource($build, $propId, $propDefinition, $prop_source_config, $contexts);
+    $property_value = $build['#props'][$propId] ?? NULL;
+    if (empty($property_value)) {
+      return NULL;
+    }
+    $prop_typ_types = [];
+    if (isset($this->propDefinition['type'])) {
+      // Type can be an array of types or a single type.
+      $prop_typ_types = is_array($this->propDefinition['type']) ? $this->propDefinition['type'] : [$this->propDefinition['type']];
+    }
+    return $this->transTypeProp($property_value, $prop_typ_types);
+  }
+
+}
diff --git a/modules/ui_patterns_field/tests/fixtures/tests.ui_patterns_source.yml b/modules/ui_patterns_field/tests/fixtures/tests.ui_patterns_source.yml
new file mode 100644
index 0000000000000000000000000000000000000000..80f348d160b73d4817737024289a23510f963efb
--- /dev/null
+++ b/modules/ui_patterns_field/tests/fixtures/tests.ui_patterns_source.yml
@@ -0,0 +1,33 @@
+---
+# this test demonstrates a simple mapping  of a prop
+# from a field to a component
+# this fails if the field is not working (not saving)
+# or if the mapping is not working
+ui_patterns_source_mapping_simple_1:
+  component:
+    component_id: ui_patterns_test:test-component
+    props:
+      string:
+        source_id: entity_field
+        source:
+          derivable_context: 'field:node:page:field_ui_patterns_source_1'
+          'field:node:page:field_ui_patterns_source_1':
+            value:
+              source_id: 'ui_patterns_source:node:field_ui_patterns_source_1'
+  entity:
+    field_ui_patterns_source_1:
+      source_id: 'component'
+      source:
+        component:
+          component_id: 'ui_patterns_test:test-component'
+          props:
+            string:
+              source_id: 'textfield'
+              source:
+                value: 'value_text_1'
+  contexts:
+    field_name: 'field_ui_patterns_source_1'
+  output:
+    props:
+      string:
+        value: 'value_text_1'
diff --git a/modules/ui_patterns_field/tests/src/Kernel/Source/UIPatternsSourceFieldPropertySourceTest.php b/modules/ui_patterns_field/tests/src/Kernel/Source/UIPatternsSourceFieldPropertySourceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c05f1998900fe94375586962ac23b4b4af386df4
--- /dev/null
+++ b/modules/ui_patterns_field/tests/src/Kernel/Source/UIPatternsSourceFieldPropertySourceTest.php
@@ -0,0 +1,36 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\ui_patterns_field\Kernel\Source;
+
+use Drupal\Tests\ui_patterns\Kernel\SourcePluginsTestBase;
+
+/**
+ * Test UIPatternsSourceFieldPropertySource.
+ *
+ * @coversDefaultClass \Drupal\ui_patterns_field\Plugin\UiPatterns\Source\UIPatternsSourceFieldPropertySource
+ * @group ui_patterns_field
+ */
+class UIPatternsSourceFieldPropertySourceTest extends SourcePluginsTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['ui_patterns_field'];
+
+  /**
+   * Test Field Property Plugin.
+   */
+  public function testPlugin(): void {
+    $testData = self::loadTestDataFixture(__DIR__ . "/../../../fixtures/tests.ui_patterns_source.yml");
+    $testSets = $testData->getTestSets();
+    foreach ($testSets as $test_set_name => $test_set) {
+      if (!str_starts_with($test_set_name, 'ui_patterns_source_')) {
+        continue;
+      }
+      $this->runSourcePluginTest($test_set);
+    }
+  }
+
+}
diff --git a/modules/ui_patterns_field/ui_patterns_field.info.yml b/modules/ui_patterns_field/ui_patterns_field.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..86ca2f6fd95f995327e1a9bfba5ca3aa7c6c1a97
--- /dev/null
+++ b/modules/ui_patterns_field/ui_patterns_field.info.yml
@@ -0,0 +1,8 @@
+name: UI Patterns Field
+type: module
+description: Use UI components and UI Patterns sources in fields.
+core_version_requirement: ^10.3 || ^11
+lifecycle: experimental
+package: "User interface (experimental)"
+dependencies:
+  - ui_patterns:ui_patterns
diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php
index e2d187c5b5d755149ee05def1446758a44bf2e09..bad4a2fb3efdfb1de7d3bb14cb3faf586c84fe7c 100644
--- a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php
+++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php
@@ -4,14 +4,8 @@ declare(strict_types=1);
 
 namespace Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter;
 
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Field\FormatterBase;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\Context\EntityContext;
 use Drupal\Core\Theme\ComponentPluginManager;
 use Drupal\ui_patterns\Form\ComponentSettingsFormBuilderTrait;
 use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
@@ -32,69 +26,15 @@ abstract class ComponentFormatterBase extends FormatterBase {
    */
   protected ComponentPluginManager $componentPluginManager;
 
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The entity field manager.
-   *
-   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
-   */
-  protected $entityFieldManager;
-
-  /**
-   * The sample entity generator.
-   *
-   * @var \Drupal\ui_patterns\Entity\SampleEntityGenerator
-   */
-  protected $sampleEntityGenerator;
-
-  /**
-   * The chain context entity resolver.
-   *
-   * @var \Drupal\ui_patterns\Resolver\ContextEntityResolverInterface
-   */
-  protected $chainContextEntityResolver;
-
-  /**
-   * The provided plugin contexts.
-   *
-   * @var array|null
-   */
-  protected $context = NULL;
-
   /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
     $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
     $instance->componentPluginManager = $container->get('plugin.manager.sdc');
-    $instance->entityTypeManager = $container->get('entity_type.manager');
-    $instance->entityFieldManager = $container->get('entity_field.manager');
-
-    $instance->sampleEntityGenerator = $container->get('ui_patterns.sample_entity_generator');
-    $instance->chainContextEntityResolver = $container->get('ui_patterns.chain_context_entity_resolver');
-
     return $instance;
   }
 
-  /**
-   * Set the context.
-   *
-   * @param array $context
-   *   Context.
-   *
-   * @return void
-   *   Nothing.
-   */
-  public function setContext(array $context): void {
-    $this->context = $context;
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -152,46 +92,6 @@ abstract class ComponentFormatterBase extends FormatterBase {
     ];
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkEntityHasField(EntityInterface $entity, string $entity_type_id, string $field_name) : bool {
-    $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());
-    return ($entity->getEntityTypeId() === $entity_type_id &&
-      array_key_exists($field_name, $field_definitions));
-  }
-
-  /**
-   * Find an entity bundle which has a field.
-   *
-   * @param string $entity_type_id
-   *   The entity type id.
-   * @param string $field_name
-   *   The field name to be found in searched bundle.
-   *
-   * @return string
-   *   The bundle.
-   */
-  protected function findEntityBundleWithField(string $entity_type_id, string $field_name) : string {
-    // @todo better implementation with service 'entity_type.bundle.info'
-    $bundle = $entity_type_id;
-    $bundle_entity_type = $this->entityTypeManager->getDefinition($entity_type_id)->getBundleEntityType();
-    if (NULL !== $bundle_entity_type) {
-      $bundle_list = $this->entityTypeManager->getStorage($bundle_entity_type)->loadMultiple();
-      if (count($bundle_list) > 0) {
-        foreach ($bundle_list as $bundle_entity) {
-          $bundle_to_test = (string) $bundle_entity->id();
-          $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle_to_test);
-          if (array_key_exists($field_name, $definitions)) {
-            $bundle = $bundle_to_test;
-            break;
-          }
-        }
-      }
-    }
-    return $bundle;
-  }
-
   /**
    * Set the context of field and entity (override the method trait).
    *
@@ -202,40 +102,8 @@ abstract class ComponentFormatterBase extends FormatterBase {
    *   Source contexts.
    */
   protected function getComponentSourceContexts(?FieldItemListInterface $items = NULL): array {
-    $contexts = array_merge($this->context ?? [], $this->getThirdPartySetting('ui_patterns', 'context') ?? []);
-    $field_definition = $this->fieldDefinition;
-    $field_name = $field_definition->getName() ?? "";
-    $contexts['field_name'] = new Context(ContextDefinition::create('string'), $field_name);
-    $contexts = RequirementsContext::addToContext(["field_formatter"], $contexts);
-    $bundle = $field_definition->getTargetBundle();
-    $contexts['bundle'] = new Context(ContextDefinition::create('string'), $bundle ?? "");
-    // Get the entity.
-    $entity_type_id = $field_definition->getTargetEntityTypeId();
-    // When field items are available, we can get the entity directly.
-    $entity = ($items) ? $items->getEntity() : NULL;
-    if (!$entity) {
-      $entity = $this->chainContextEntityResolver->guessEntity($contexts);
-    }
-    if (!$entity_type_id) {
-      return $contexts;
-    }
-    if (!$entity || !$this->checkEntityHasField($entity, $entity_type_id, $field_name)) {
-      // Generate a default bundle when it is missing,
-      // this covers contexts like the display of a field in a view.
-      // the bundle selected should have the field in definition...
-      $entity = !empty($bundle) ? $this->sampleEntityGenerator->get($entity_type_id, $bundle) :
-        $this->sampleEntityGenerator->get($entity_type_id, $this->findEntityBundleWithField($entity_type_id, $field_name));
-
-    }
-    $contexts['entity'] = EntityContext::fromEntity($entity);
-    return $contexts;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function isApplicable(FieldDefinitionInterface $field_definition) {
-    return ($field_definition->getTargetEntityTypeId() !== NULL) && parent::isApplicable($field_definition);
+    $contexts = parent::getComponentSourceContexts($items);
+    return RequirementsContext::addToContext(["field_formatter"], $contexts);
   }
 
   /**
diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/FormatterBase.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/FormatterBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..119a421a115395ec591f0a02de5eccd98c4e7ad4
--- /dev/null
+++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/FormatterBase.php
@@ -0,0 +1,174 @@
+<?php
+
+namespace Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FormatterBase as FieldFormatterBase;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\ui_patterns\SourcePluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Base class for UI Patterns field formatters.
+ */
+abstract class FormatterBase extends FieldFormatterBase {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The entity field manager.
+   *
+   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * The sample entity generator.
+   *
+   * @var \Drupal\ui_patterns\Entity\SampleEntityGenerator
+   */
+  protected $sampleEntityGenerator;
+
+  /**
+   * The chain context entity resolver.
+   *
+   * @var \Drupal\ui_patterns\Resolver\ContextEntityResolverInterface
+   */
+  protected $chainContextEntityResolver;
+
+  /**
+   * The provided plugin contexts.
+   *
+   * @var array|null
+   */
+  protected $context = NULL;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $instance->entityTypeManager = $container->get('entity_type.manager');
+    $instance->entityFieldManager = $container->get('entity_field.manager');
+    $instance->sampleEntityGenerator = $container->get('ui_patterns.sample_entity_generator');
+    $instance->chainContextEntityResolver = $container->get('ui_patterns.chain_context_entity_resolver');
+    return $instance;
+  }
+
+  /**
+   * Set the context.
+   *
+   * @param array $context
+   *   Context.
+   *
+   * @return void
+   *   Nothing.
+   */
+  public function setContext(array $context): void {
+    $this->context = $context;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function checkEntityHasField(EntityInterface $entity, string $entity_type_id, string $field_name) : bool {
+    $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());
+    return ($entity->getEntityTypeId() === $entity_type_id &&
+      array_key_exists($field_name, $field_definitions));
+  }
+
+  /**
+   * Find an entity bundle which has a field.
+   *
+   * @param string $entity_type_id
+   *   The entity type id.
+   * @param string $field_name
+   *   The field name to be found in searched bundle.
+   *
+   * @return string
+   *   The bundle.
+   */
+  protected function findEntityBundleWithField(string $entity_type_id, string $field_name) : string {
+    // @todo better implementation with service 'entity_type.bundle.info'
+    $bundle = $entity_type_id;
+    $bundle_entity_type = $this->entityTypeManager->getDefinition($entity_type_id)->getBundleEntityType();
+    if (NULL !== $bundle_entity_type) {
+      $bundle_list = $this->entityTypeManager->getStorage($bundle_entity_type)->loadMultiple();
+      if (count($bundle_list) > 0) {
+        foreach ($bundle_list as $bundle_entity) {
+          $bundle_to_test = (string) $bundle_entity->id();
+          $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle_to_test);
+          if (array_key_exists($field_name, $definitions)) {
+            $bundle = $bundle_to_test;
+            break;
+          }
+        }
+      }
+    }
+    return $bundle;
+  }
+
+  /**
+   * Set the context of field and entity (override the method trait).
+   *
+   * @param ?FieldItemListInterface $items
+   *   Field items when available.
+   *
+   * @return array
+   *   Source contexts.
+   */
+  protected function getComponentSourceContexts(?FieldItemListInterface $items = NULL): array {
+    $contexts = array_merge($this->context ?? [], $this->getThirdPartySetting('ui_patterns', 'context') ?? []);
+    $field_definition = $this->fieldDefinition;
+    $field_name = $field_definition->getName() ?? "";
+    $contexts['field_name'] = new Context(ContextDefinition::create('string'), $field_name);
+    $bundle = $field_definition->getTargetBundle();
+    $contexts['bundle'] = new Context(ContextDefinition::create('string'), $bundle ?? "");
+    // Get the entity.
+    $entity_type_id = $field_definition->getTargetEntityTypeId();
+    // When field items are available, we can get the entity directly.
+    $entity = ($items) ? $items->getEntity() : NULL;
+    if (!$entity) {
+      $entity = $this->chainContextEntityResolver->guessEntity($contexts);
+    }
+    if (!$entity_type_id) {
+      return $contexts;
+    }
+    if (!$entity || !$this->checkEntityHasField($entity, $entity_type_id, $field_name)) {
+      // Generate a default bundle when it is missing,
+      // this covers contexts like the display of a field in a view.
+      // the bundle selected should have the field in definition...
+      $entity = !empty($bundle) ? $this->sampleEntityGenerator->get($entity_type_id, $bundle) :
+        $this->sampleEntityGenerator->get($entity_type_id, $this->findEntityBundleWithField($entity_type_id, $field_name));
+
+    }
+    $contexts['entity'] = EntityContext::fromEntity($entity);
+    return $contexts;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    return ($field_definition->getTargetEntityTypeId() !== NULL) && parent::isApplicable($field_definition);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    $dependencies = parent::calculateDependencies();
+    SourcePluginBase::mergeConfigDependencies($dependencies, ["module" => ["ui_patterns_field_formatters"]]);
+    return $dependencies;
+  }
+
+}
diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/SourceFormatter.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/SourceFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..1dcd8746ced67f996a4e3ecca370533b4f82e0b6
--- /dev/null
+++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/SourceFormatter.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\Attribute\FieldFormatter;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Formatter to render the file URI to its download path.
+ */
+#[FieldFormatter(
+  id: 'ui_patterns_source',
+  label: new TranslatableMarkup('Render source (UI Patterns)'),
+  field_types: ['ui_patterns_source'],
+)]
+class SourceFormatter extends FormatterBase {
+
+  /**
+   * The component element builder.
+   *
+   * @var \Drupal\ui_patterns\Element\ComponentElementBuilder
+   */
+  protected $componentElementBuilder;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $instance->componentElementBuilder = $container->get('ui_patterns.component_element_builder');
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    $settings = parent::defaultSettings();
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items, $langcode) {
+    $fake_build = [];
+    $contexts = $this->getComponentSourceContexts($items);
+    $contexts['ui_patterns:lang_code'] = new Context(new ContextDefinition('any'), $langcode);
+    $contexts['ui_patterns:field:items'] = new Context(new ContextDefinition('any'), $items);
+    for ($field_item_index = 0; $field_item_index < $items->count(); $field_item_index++) {
+      $contexts['ui_patterns:field:index'] = new Context(new ContextDefinition('integer'), $field_item_index);
+      $source_with_configuration = $items->get($field_item_index)->getValue();
+      $fake_build = $this->componentElementBuilder->buildSource($fake_build, 'content', [], $source_with_configuration, $contexts);
+    }
+    $build = $fake_build['#slots']['content'] ?? [];
+    $build['#cache'] = $fake_build['#cache'] ?? [];
+    return $build;
+  }
+
+}
diff --git a/src/Element/ComponentForm.php b/src/Element/ComponentForm.php
index 87724d47c262a9528ee1ea8114f021bac97ef8cc..903d54c383b1f69d46117a4238eb626e50bb96c3 100644
--- a/src/Element/ComponentForm.php
+++ b/src/Element/ComponentForm.php
@@ -63,6 +63,10 @@ class ComponentForm extends ComponentFormBase {
       '#input' => TRUE,
       '#multiple' => FALSE,
       '#component_required' => TRUE,
+      '#prop_filter' => NULL,
+      '#wrap' => TRUE,
+      '#render_headings' => TRUE,
+      '#render_sources' => TRUE,
       '#default_value' => NULL,
       '#source_contexts' => [],
       '#tag_filter' => [],
@@ -74,7 +78,7 @@ class ComponentForm extends ComponentFormBase {
       ],
       '#theme_wrappers' => ['form_element'],
       '#after_build' => [
-              [$class, 'afterBuild'],
+        [$class, 'afterBuild'],
       ],
     ];
   }
@@ -201,6 +205,10 @@ class ComponentForm extends ComponentFormBase {
         $component_id,
         $element['#default_value']['variant_id'] ?? NULL,
       );
+      $prop_filter = $element['#prop_filter'] ?? NULL;
+      if (is_array($prop_filter) && !in_array("variant", $prop_filter)) {
+        $element['variant_id']['#access'] = FALSE;
+      }
     }
     $element['slots'] = self::buildSlotsForm($element, $component_id);
     $element['props'] = self::buildPropsForm($element, $component_id);
@@ -261,9 +269,10 @@ class ComponentForm extends ComponentFormBase {
       "#prop_id" => 'variant',
       '#default_value' => $default_variant_id,
       '#source_contexts' => $element['#source_contexts'],
+      '#render_sources' => $element['#render_sources'] ?? TRUE,
       '#tag_filter' => $element['#tag_filter'],
       '#ajax_url' => $element['#ajax_url'] ?? NULL,
-      '#wrap' => TRUE,
+      '#wrap' => $element['#wrap'] ?? TRUE,
     ];
   }
 
@@ -280,6 +289,9 @@ class ComponentForm extends ComponentFormBase {
       '#ajax_url' => $element['#ajax_url'] ?? NULL,
       '#access' => $element['#render_slots'] ?? TRUE,
       '#default_value' => $element['#default_value']['slots'] ?? NULL,
+      '#wrap' => $element['#wrap'] ?? TRUE,
+      '#render_headings' => $element['#render_headings'] ?? TRUE,
+      '#render_sources' => $element['#render_sources'] ?? TRUE,
     ];
   }
 
@@ -294,6 +306,10 @@ class ComponentForm extends ComponentFormBase {
       '#source_contexts' => $element['#source_contexts'],
       '#tag_filter' => $element['#tag_filter'],
       '#ajax_url' => $element['#ajax_url'] ?? NULL,
+      '#prop_filter' => $element['#prop_filter'] ?? NULL,
+      '#render_headings' => $element['#render_headings'] ?? TRUE,
+      '#render_sources' => $element['#render_sources'] ?? TRUE,
+      '#wrap' => $element['#wrap'] ?? TRUE,
       '#access' => $element['#render_props'] ?? TRUE,
       '#default_value' => [
         'props' => $element['#default_value']['props'] ?? [],
diff --git a/src/Element/ComponentPropForm.php b/src/Element/ComponentPropForm.php
index 07eff59d07a29189665a9769f9796c33c601ba60..ac48327d8cc5254b8f1f14afb5af683b102eb576 100644
--- a/src/Element/ComponentPropForm.php
+++ b/src/Element/ComponentPropForm.php
@@ -53,6 +53,7 @@ class ComponentPropForm extends ComponentFormBase {
       '#slot_id' => NULL,
     // Wrapped (into details/summary) or not.
       '#wrap' => FALSE,
+      '#render_sources' => TRUE,
       '#process' => [
         [$class, 'buildForm'],
         [$class, 'processPropOrSlot'],
@@ -97,9 +98,21 @@ class ComponentPropForm extends ComponentFormBase {
       'source_id' => $source_selector,
       'source' => array_merge($source_form, ['#prop_id' => $prop_id]),
     ];
+    if (!($element['#render_sources'] ?? TRUE)) {
+      $element['source_id'] = [
+        '#type' => 'hidden',
+        '#value' => $selected_source->getPluginId(),
+      ];
+    }
     $element = static::addRequired($element, $prop_id);
-    if ($prop_id === "variant") {
-      $element["source"]["value"]["#title"] = $element["#title"];
+    // This allows "widgets" to have a title when #wrap is unset.
+    if (!($element['#wrap'] ?? TRUE) && isset($element["source"]["value"])) {
+      if (empty($element["source"]["value"]["#title"])) {
+        $element["source"]["value"]["#title"] = $element["#title"];
+      }
+      if (empty($element["source"]["value"]["#description"])) {
+        $element["source"]["value"]["#description"] = $element['#description'] ?? NULL;
+      }
     }
     return $element;
   }
diff --git a/src/Element/ComponentPropsForm.php b/src/Element/ComponentPropsForm.php
index 1e54e93673febd30974f7b409c3abcdd34fb3de0..9f284d4a7cb399e0f296ae907c4e54b7224d7498 100644
--- a/src/Element/ComponentPropsForm.php
+++ b/src/Element/ComponentPropsForm.php
@@ -55,6 +55,10 @@ class ComponentPropsForm extends ComponentFormBase {
       '#component_id' => NULL,
       '#source_contexts' => [],
       '#tag_filter' => [],
+      '#prop_filter' => NULL,
+      '#render_headings' => TRUE,
+      '#render_sources' => TRUE,
+      '#wrap' => TRUE,
       '#process' => [
         [$class, 'buildForm'],
       ],
@@ -74,10 +78,13 @@ class ComponentPropsForm extends ComponentFormBase {
       return $element;
     }
     $configuration = $element['#default_value']['props'] ?? [];
-    $prop_heading = new FormattableMarkup("<p><strong>@title</strong></p>", ["@title" => t("Props")]);
-    $element[] = [
-      '#markup' => $prop_heading,
-    ];
+    if ($element['#render_headings']) {
+      $prop_heading = new FormattableMarkup("<p><strong>@title</strong></p>", ["@title" => t("Props")]);
+      $element[] = [
+        '#markup' => $prop_heading,
+      ];
+    }
+    $prop_filter = $element['#prop_filter'] ?? NULL;
     foreach ($props as $prop_id => $prop) {
       if ($prop_id === 'variant') {
         continue;
@@ -92,11 +99,15 @@ class ComponentPropsForm extends ComponentFormBase {
         '#tag_filter' => $element['#tag_filter'],
         '#component_id' => $component->getPluginId(),
         '#prop_id' => $prop_id,
-        '#wrap' => TRUE,
+        '#wrap' => $element['#wrap'] ?? TRUE,
+        '#render_sources' => $element['#render_sources'] ?? TRUE,
       ];
+      if (is_array($prop_filter) && !in_array($prop_id, $prop_filter)) {
+        $element[$prop_id]['#access'] = FALSE;
+      }
     }
     if (count(Element::children($element)) === 0) {
-      hide($element);
+      $element['#access'] = FALSE;
     }
     return $element;
   }
diff --git a/src/Element/ComponentSlotsForm.php b/src/Element/ComponentSlotsForm.php
index 063617c1206a362cc60e57f7d09cfdbcba16b278..c2749ecdddcabcfac6e1d24d75a67d932cf7abd1 100644
--- a/src/Element/ComponentSlotsForm.php
+++ b/src/Element/ComponentSlotsForm.php
@@ -50,6 +50,8 @@ class ComponentSlotsForm extends ComponentFormBase {
       '#component_id' => NULL,
       '#source_contexts' => [],
       '#tag_filter' => [],
+      '#wrap' => TRUE,
+      '#render_headings' => TRUE,
       '#process' => [
         [$class, 'buildForm'],
       ],
@@ -99,15 +101,17 @@ class ComponentSlotsForm extends ComponentFormBase {
     if (!isset($component->metadata->slots) || count(
         $component->metadata->slots
       ) === 0) {
-      hide($element);
+      $element['#access'] = FALSE;
       return $element;
     }
     $contexts = $element['#source_contexts'] ?? [];
     $configuration = $element['#default_value'] ?? [];
-    $slot_heading = new FormattableMarkup("<p><strong>@title</strong></p>", ["@title" => t("Slots")]);
-    $element[] = [
-      '#markup' => $slot_heading,
-    ];
+    if ($element['#render_headings']) {
+      $slot_heading = new FormattableMarkup("<p><strong>@title</strong></p>", ["@title" => t("Slots")]);
+      $element[] = [
+        '#markup' => $slot_heading,
+      ];
+    }
     foreach ($component->metadata->slots as $slot_id => $slot) {
       $element[$slot_id] = [
         '#title' => $slot['title'] ?? '',
@@ -117,6 +121,7 @@ class ComponentSlotsForm extends ComponentFormBase {
         '#component_id' => $component->getPluginId(),
         '#slot_id' => $slot_id,
         '#source_contexts' => $contexts,
+        '#wrap' => $element['#wrap'] ?? TRUE,
         '#tag_filter' => $element['#tag_filter'],
         '#prefix' => "<div class='component-form-slot'>",
         '#suffix' => "</div>",
diff --git a/src/Plugin/UiPatterns/Source/AttributesWidget.php b/src/Plugin/UiPatterns/Source/AttributesWidget.php
index cae736aad6f08d9ab3bcbea942faa1638d23fdc9..04e9fdcd09396984ca11c3f677bdffbce7ebd3e5 100644
--- a/src/Plugin/UiPatterns/Source/AttributesWidget.php
+++ b/src/Plugin/UiPatterns/Source/AttributesWidget.php
@@ -21,6 +21,7 @@ use Drupal\ui_patterns\UnicodePatternValidatorTrait;
   label: new TranslatableMarkup('Attributes'),
   description: new TranslatableMarkup('Textfield with double-quoted values or a space-separated list of HTML classes.'),
   prop_types: ['attributes'],
+  tags: ['widget', 'widget:dismissible'],
 )]
 class AttributesWidget extends SourcePluginPropValueWidget implements TrustedCallbackInterface {
 
diff --git a/src/Plugin/UiPatterns/Source/FieldPropertySource.php b/src/Plugin/UiPatterns/Source/FieldPropertySource.php
index ecd9e5fdab72bbce02d3289d82bcc898180b32c8..7bd72e27e27b9a062d29663b1eb91f9bbcb7b546 100644
--- a/src/Plugin/UiPatterns/Source/FieldPropertySource.php
+++ b/src/Plugin/UiPatterns/Source/FieldPropertySource.php
@@ -54,7 +54,7 @@ class FieldPropertySource extends FieldValueSourceBase {
    * @return bool|float|int
    *   The value converted.
    */
-  private function transTypeProp(mixed $value, array $prop_types): mixed {
+  protected function transTypeProp(mixed $value, array $prop_types): mixed {
     foreach ($prop_types as $prop_type) {
       $converted = match ($prop_type) {
         'integer' => is_int($value) ? $value : (int) $value,
diff --git a/src/Plugin/UiPatterns/Source/ListTextareaWidget.php b/src/Plugin/UiPatterns/Source/ListTextareaWidget.php
index 313eeadbc793a54f4dde0f04f3b74d8f6a80b67d..e5b15bc6e8d87f80223b772411fdce3f0b145987 100644
--- a/src/Plugin/UiPatterns/Source/ListTextareaWidget.php
+++ b/src/Plugin/UiPatterns/Source/ListTextareaWidget.php
@@ -16,7 +16,8 @@ use Drupal\ui_patterns\SourcePluginBase;
   id: 'list_textarea',
   label: new TranslatableMarkup('Textarea for list'),
   description: new TranslatableMarkup('One item by line.'),
-  prop_types: ['list']
+  prop_types: ['list'],
+  tags: ['widget', 'widget:dismissible']
 )]
 class ListTextareaWidget extends SourcePluginBase {