diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentAllFormatter.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentAllFormatter.php
index af8edc06f8b6f4eaaeefdaec486240db13a66032..fefcc6540dccc8986107c7eb22e918e1ace7dc76 100644
--- a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentAllFormatter.php
+++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentAllFormatter.php
@@ -38,7 +38,14 @@ class ComponentAllFormatter extends FormatterBase {
    * {@inheritdoc}
    */
   public static function defaultSettings() {
-    return parent::defaultSettings() + self::getComponentSettingsFormDefault();
+    return parent::defaultSettings() + self::getComponentFormDefault();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getComponentSettings(): array {
+    return $this->getSettings();
   }
 
   /**
@@ -52,8 +59,7 @@ class ComponentAllFormatter extends FormatterBase {
    * {@inheritdoc}
    */
   public function viewElements(FieldItemListInterface $items, $langcode) {
-    $build = $this->buildComponentSettingsData();
-    return $build;
+    // @todo Implement viewElements() method.
   }
 
 }
diff --git a/modules/ui_patterns_field_formatters/ui_patterns_field_formatters.module b/modules/ui_patterns_field_formatters/ui_patterns_field_formatters.module
index 80c4271af5e6d0c72a0ee44d049f228c2c7534ea..617563a751a26ca7d021556ef4b60363463e3a0e 100644
--- a/modules/ui_patterns_field_formatters/ui_patterns_field_formatters.module
+++ b/modules/ui_patterns_field_formatters/ui_patterns_field_formatters.module
@@ -1,5 +1,10 @@
 <?php
 
+/**
+ * @file
+ * Adds UI Patterns component field formatter to existing fields.
+ */
+
 declare(strict_types = 1);
 
 /**
diff --git a/modules/ui_patterns_layouts/ui_patterns_layouts.module b/modules/ui_patterns_layouts/ui_patterns_layouts.module
index 959102ac15855e275d29e3a63527c57e310cd25a..0095c3e7559d7de2ecfeeaf2db5389b4da04a65b 100644
--- a/modules/ui_patterns_layouts/ui_patterns_layouts.module
+++ b/modules/ui_patterns_layouts/ui_patterns_layouts.module
@@ -1,5 +1,9 @@
 <?php
 
+/**
+ * @file
+ */
+
 declare(strict_types = 1);
 
 /**
@@ -8,7 +12,6 @@ declare(strict_types = 1);
  */
 
 use Drupal\Core\Layout\LayoutDefinition;
-use Drupal\ui_patterns_layouts\Plugin\Layout\ComponentLayout;
 
 /**
  * Implements hook_layout_alter().
diff --git a/modules/ui_patterns_library/ui_patterns_library.module b/modules/ui_patterns_library/ui_patterns_library.module
index d36533a0c3a5f8f3340d03dd8fa1732df6443f61..b7222e15de9f8358ee7b52bb7b11fca6bd13a270 100644
--- a/modules/ui_patterns_library/ui_patterns_library.module
+++ b/modules/ui_patterns_library/ui_patterns_library.module
@@ -1,5 +1,9 @@
 <?php
 
+/**
+ * @file
+ */
+
 declare(strict_types = 1);
 
 /**
diff --git a/modules/ui_patterns_views/src/Plugin/views/row/ComponentRow.php b/modules/ui_patterns_views/src/Plugin/views/row/ComponentRow.php
index 22657b468ecf570b24e72484de7d1b5a52040477..0f91299a7724e694b3d5a0934069d83df604e853 100644
--- a/modules/ui_patterns_views/src/Plugin/views/row/ComponentRow.php
+++ b/modules/ui_patterns_views/src/Plugin/views/row/ComponentRow.php
@@ -4,7 +4,7 @@ declare(strict_types = 1);
 
 namespace Drupal\ui_patterns_views\Plugin\views\row;
 
-use Drupal\ui_patterns\Form\PatternDisplayFormTrait;
+use Drupal\ui_patterns\Form\ComponentSettingsFormBuilderTrait;
 use Drupal\views\Plugin\views\row\Fields;
 
 /**
@@ -22,6 +22,13 @@ use Drupal\views\Plugin\views\row\Fields;
  */
 class ComponentRow extends Fields {
 
-  use PatternDisplayFormTrait;
+  use ComponentSettingsFormBuilderTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getComponentSettings(): array {
+    return $this->options;
+  }
 
 }
diff --git a/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php b/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php
index ce4eacebd8acf6baf4e2f19a15d0842afd75151a..9cca5a0c121e4ff9c53c25a79559e4d2da666465 100755
--- a/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php
+++ b/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php
@@ -5,7 +5,8 @@ declare(strict_types = 1);
 namespace Drupal\ui_patterns_views\Plugin\views\style;
 
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\ui_patterns\Form\ComponentFormBuilderTrait;
+use Drupal\Core\Url;
+use Drupal\ui_patterns\Form\ComponentSettingsFormBuilderTrait;
 use Drupal\views\Plugin\views\style\StylePluginBase;
 
 /**
@@ -23,40 +24,53 @@ use Drupal\views\Plugin\views\style\StylePluginBase;
  */
 class ComponentStyle extends StylePluginBase {
 
-  use ComponentFormBuilderTrait;
+  use ComponentSettingsFormBuilderTrait;
 
   /**
    * {@inheritdoc}
    */
   protected $usesRowPlugin = TRUE;
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $usesOptions = TRUE;
+
   /**
    * {@inheritdoc}
    */
   protected function defineOptions(): array {
-    return parent::defineOptions() + self::getComponentFormDefault();
+    return parent::defineOptions() + ['ui_patterns' => ['default' => self::getComponentFormDefault()['ui_patterns']]];
   }
 
   /**
    * {@inheritdoc}
    */
   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+    $ui_patterns_form = $this->componentSettingsForm($form, $form_state);
+    $form['ui_patterns'] = $ui_patterns_form['ui_patterns'];
     parent::buildOptionsForm($form, $form_state);
-    $configuration = $this->options ?: $this->defineOptions();
-    return $this->buildComponentsForm($form_state, $configuration, NULL, TRUE, TRUE);
   }
 
   /**
    * {@inheritdoc}
    */
-  public function render(): array {
-    $build = parent::render();
-    $ui_patterns = $this->options['ui_patterns'];
+  public function getComponentSettings(): array {
+    return $this->options;
+  }
 
-    // We are using groups ($usesRowPlugin)
-    foreach ($build as $delta => $group) {
-    }
-    return $build;
+  /**
+   * {@inheritdoc}
+   */
+  protected function getAjaxUrl(FormStateInterface $form_state): ?Url {
+    return views_ui_build_form_url($form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render(): array {
+    return [];
   }
 
 }
diff --git a/modules/ui_patterns_views/ui_patterns_views.module b/modules/ui_patterns_views/ui_patterns_views.module
new file mode 100644
index 0000000000000000000000000000000000000000..89692c1d21443e8b6b3abe1589afe30ef869e116
--- /dev/null
+++ b/modules/ui_patterns_views/ui_patterns_views.module
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Adds views configuration changes after AJAX interactions.
+ */
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements ui_patterns_form_configuration_changed().
+ */
+function ui_patterns_views_ui_patterns_form_configuration_changed(FormStateInterface $form_state, array $configuration) {
+  /** @var \Drupal\views_ui\ViewUI $view */
+  $view = $form_state->get('view');
+  if ($view !== NULL) {
+    /** @var \Drupal\views\ViewExecutable $executable */
+    $executable = $form_state->get('view')->getExecutable();
+    $display_id = $form_state->get('display_id');
+    $type = str_replace('_options', '', $form_state->get('type'));
+    $executable->displayHandlers->get($display_id)->setOption($type, ['type' => 'ui_patterns', 'options' => ['ui_patterns' => $configuration], 'grouping' => []]);
+    $view->cacheSet();
+    $form_state->set('rerender', TRUE);
+  }
+}
diff --git a/src/Form/ComponentFormBuilderState.php b/src/Form/ComponentFormBuilderState.php
new file mode 100644
index 0000000000000000000000000000000000000000..15ab12bec3a6019f55058b7c1b21567303d909c4
--- /dev/null
+++ b/src/Form/ComponentFormBuilderState.php
@@ -0,0 +1,190 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\ui_patterns\Form;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Component Form Builder State
+ *
+ * Stores the component form builder states and AJAX handlers.
+ */
+final class ComponentFormBuilderState {
+
+  /**
+   * Return the form api storage subkey.
+   */
+  private static function getComponentStorageSubKey(FormStateInterface $form_state, $storage_sub_key = 'default'): string {
+    $trigger_element = $form_state->getTriggeringElement();
+    return $trigger_element['#ui_patterns']['storage_sub_key'] ?? $storage_sub_key;
+  }
+
+  /**
+   * Returns component storage.
+   */
+  public static function getComponentStorage(FormStateInterface $form_state, $storage_sub_key = 'default'): array {
+    $storage = $form_state->getStorage();
+    return $storage['ui_patterns'][self::getComponentStorageSubKey($form_state, $storage_sub_key)] ?? [];
+  }
+
+  /**
+   * Sets the component storage to form_state storage.
+   */
+  public static function setComponentStorage(
+    $storage,
+    FormStateInterface $form_state,
+    $storage_sub_key = 'default'
+  ): void {
+    $origin_storage = $form_state->getStorage();
+
+    $origin_storage['ui_patterns'][self::getComponentStorageSubKey($form_state, $storage_sub_key)] = $storage;
+    $form_state->setStorage($origin_storage);
+  }
+
+  /**
+   * Sets the component state.
+   */
+  public static function setComponentFormState(
+    $key,
+    $value,
+    FormStateInterface $form_state,
+    $storage_sub_key = 'default',
+    $invoke_hook = TRUE
+  ): void {
+    if ($key === 'configuration' && $invoke_hook) {
+      \Drupal::moduleHandler()->invokeAll('ui_patterns_form_configuration_changed', [$form_state, $value]);
+    }
+    $storage = self::getComponentStorage($form_state, $storage_sub_key);
+    $storage[$key] = $value;
+    self::setComponentStorage($storage, $form_state, $storage_sub_key);
+  }
+
+  /**
+   * Get the current form state.
+   */
+  public static function getComponentFormState(
+    $key,
+    FormStateInterface $form_state,
+    $storage_sub_key = 'default'
+  ): mixed {
+    $storage = self::getComponentStorage($form_state, $storage_sub_key);
+    return $storage[$key] ?? NULL;
+  }
+
+  /**
+   * Ajax submit handler: Add slot item.
+   */
+  public static function addSlotItemSubmitAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+    $button = $form_state->getTriggeringElement();
+    $slot_id = $button['#slot_id'];
+    $source_id = $button['#source_id'];
+    $configuration = self::getComponentFormState(
+      'configuration',
+      $form_state
+    );
+    $configuration['component']['slots'][$slot_id]['sources'][] = ['id' => $source_id];
+    self::setComponentFormState('configuration', $configuration, $form_state);
+    $form_state->setRebuild();
+  }
+
+  /**
+   * Ajax handler: Add slot item.
+   */
+  public static function addSlotItemAjax(array $form, FormStateInterface $form_state) {
+    $parents = $form_state->getTriggeringElement()['#array_parents'];
+    $form = NestedArray::getValue($form, array_slice($parents, 0, -2));
+    return $form['sources'];
+  }
+
+  /**
+   * Ajax submit handler: Remove slot item.
+   */
+  public static function removeSlotItemSubmitAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+    $button = $form_state->getTriggeringElement();
+    $delta = $button['#delta'];
+    $slot_id = $button['#slot_id'];
+    $configuration = self::getComponentFormState(
+      'configuration',
+      $form_state
+    );
+    unset($configuration['component']['slots'][$slot_id]['sources'][$delta]);
+    self::setComponentFormState('configuration', $configuration, $form_state);
+    $form_state->setRebuild();
+  }
+
+  /**
+   * Ajax handler: Remove slot item.
+   */
+  final public static function removeSlotItemAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+    $parents = $form_state->getTriggeringElement()['#array_parents'];
+    return NestedArray::getValue($form, array_slice($parents, 0, -4));
+  }
+
+  /**
+   * Ajax submit handler: Change props type submit handler.
+   */
+  public static function changePropSubmitAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+    $configuration = ComponentFormBuilderState::getComponentFormState('configuration', $form_state);
+    $button = $form_state->getTriggeringElement();
+    $prop_id = $button['#prop_id'];
+    $source_id = $button['#source_id'];
+    $configuration['component']['props'][$prop_id]['source_id'] = $source_id;
+    self::setComponentFormState('configuration', $configuration, $form_state);
+    $form_state->setRebuild();
+  }
+
+  /**
+   * Ajax handler: Change prop type.
+   */
+  public static function changePropItemAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+    $parents = $form_state->getTriggeringElement()['#array_parents'];
+    return NestedArray::getValue($form, array_slice($parents, 0, -3));
+  }
+
+  /**
+   * Ajax callback for component selector change.
+   */
+  public static function changeSelectorFormChangeAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+
+    $parents = $form_state->getTriggeringElement()['#array_parents'];
+    $component_id = $form_state->getValue($form_state->getTriggeringElement()['#parents']);
+    $configuration = ComponentFormBuilderState::getComponentFormState('configuration', $form_state);
+    $configuration['component_id'] = $component_id;
+    ComponentFormBuilderState::setComponentFormState('configuration', $configuration, $form_state);
+    $sub_form = NestedArray::getValue($form, array_slice($parents, 0, -1));
+    return $sub_form['component'];
+  }
+
+  /**
+   * Ajax callback for variant selector change.
+   */
+  public static function buildComponentVariantSelectorFormChangeAjax(
+    array $form,
+    FormStateInterface $form_state
+  ) {
+    $parents = $form_state->getTriggeringElement()['#array_parents'];
+    return NestedArray::getValue($form, array_slice($parents, 0, -1));
+  }
+
+}
diff --git a/src/Form/ComponentFormBuilderTrait.php b/src/Form/ComponentFormBuilderTrait.php
index dc9c29e807317e81b720277fa6650420254c27d7..d2666efa195af43e965ff92a6fa3fecf095a9a3c 100644
--- a/src/Form/ComponentFormBuilderTrait.php
+++ b/src/Form/ComponentFormBuilderTrait.php
@@ -5,10 +5,10 @@ declare(strict_types = 1);
 namespace Drupal\ui_patterns\Form;
 
 use Drupal\Component\Utility\Html;
-use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Form\SubformState;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Url;
 use Drupal\sdc\Plugin\Component;
 use Drupal\ui_patterns\SourcePluginManager;
 
@@ -30,9 +30,12 @@ trait ComponentFormBuilderTrait {
     return [
       "ui_patterns" => [
         "component_id" => NULL,
-        "variant_id" => NULL,
-        "slots" => [],
-        "props" => [],
+
+        'component' => [
+          "variant_id" => NULL,
+          "slots" => [],
+          "props" => [],
+        ],
       ],
     ];
   }
@@ -50,6 +53,23 @@ trait ComponentFormBuilderTrait {
     return [];
   }
 
+  /**
+   * Returns the ajax url.
+   *
+   * Some integrations plugins like the views plugin provide there
+   * ajax urls for ajax form interaction. To support
+   * those plugins overwrite this function.
+   *
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   *
+   * @return \Drupal\Core\Url|null
+   *   The ajax url.
+   */
+  protected function getAjaxUrl(FormStateInterface $form_state): ?Url {
+    return NULL;
+  }
+
   /**
    * Helper function to return the component.
    */
@@ -60,58 +80,23 @@ trait ComponentFormBuilderTrait {
   }
 
   /**
-   * Return the form api storage subkey.
+   * Expand each ajax element with ajax urls.
    *
-   * Overwrite this method and provide a specifc subkey
-   * if your form handles multiple component form builders.
-   */
-  protected function getComponentStorageSubKey(): string {
-    return 'default';
-  }
-
-  /**
-   * Returns component storage.
-   */
-  private function getComponentStorage(FormStateInterface $form_state): array {
-    $storage = $form_state->getStorage();
-    return $storage['ui_patterns'][$this->getComponentStorageSubKey()] ?? [];
-  }
-
-  /**
-   * Sets the component storage to form_state storage.
-   */
-  private function seComponentStorage(
-    $storage,
-    FormStateInterface $form_state
-  ): void {
-    $origin_storage = $form_state->getStorage();
-    $origin_storage['ui_patterns'][$this->getComponentStorageSubKey(
-    )] = $storage;
-    $form_state->setStorage($origin_storage);
-  }
-
-  /**
-   * Sets the component state.
-   */
-  private function setComponentFormState(
-    $key,
-    $value,
-    FormStateInterface $form_state
-  ): void {
-    $storage = $this->getComponentStorage($form_state);
-    $storage[$key] = $value;
-    $this->seComponentStorage($storage, $form_state);
-  }
-
-  /**
-   * Get the current form state.
+   * @param array $element
+   *   The ajax element.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   *
+   * @return array
+   *   The extended ajax form.
    */
-  private function getComponentFormState(
-    $key,
-    FormStateInterface $form_state
-  ): mixed {
-    $storage = $this->getComponentStorage($form_state);
-    return $storage[$key] ?? NULL;
+  private function expandAjax(array $element, FormStateInterface $form_state): array {
+    $url = $this->getAjaxUrl($form_state);
+    if (isset($element['#ajax']) && $url) {
+      $element['#ajax']['url'] = $url;
+    }
+    $element['#ui_patterns']['storage_sub_key'] = $this->getComponentStorageSubKey();
+    return $element;
   }
 
   /**
@@ -123,7 +108,7 @@ trait ComponentFormBuilderTrait {
    * @return array
    *   Button render array.
    */
-  private function expandComponentButton(array $button_base) {
+  private function expandComponentButton(array $button_base, FormStateInterface $form_state) {
     // Do not expand elements that do not have submit handler.
     if (empty($button_base['#submit'])) {
       return $button_base;
@@ -149,7 +134,7 @@ trait ComponentFormBuilderTrait {
       ];
     }
 
-    return $button;
+    return $this->expandAjax($button, $form_state);
   }
 
   /**
@@ -194,44 +179,51 @@ trait ComponentFormBuilderTrait {
    *
    * The form contains.
    *
-   * @param Drupal\sdc\Plugin\Component $component
-   *   The component plugin.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   * @param array $configuration
+   *    The stored configuration.
+   * @param string|null $initial_component_id
+   *   The initial_component_id. If provided the component is changeable.
+   * @param boolean $render_slots
+   *   TRUE if slots are editable.
+   * @param boolean $render_props
+   *   TRUE if props are editable.
    */
   protected function buildComponentsForm(
     FormStateInterface $form_state,
-    $configuration,
-    $initial_component_id = NULL,
-    $render_slots = TRUE,
-    $render_props = TRUE
+    array $configuration,
+    string $initial_component_id = NULL,
+    bool $render_slots = TRUE,
+    bool $render_props = TRUE
   ): array {
     $form_state = $form_state instanceof SubformState ? $form_state->getCompleteFormState() : $form_state;
+
     $configuration = $configuration['ui_patterns'] ?? [];
     // TBD Make this id more flexible.
     $wrapper_id = 'ui-patterns-component';
-    $storage = $this->getComponentStorage($form_state);
+    $storage = ComponentFormBuilderState::getComponentStorage($form_state, $this->getComponentStorageSubKey());
     $storage['render_slots'] = $render_slots;
     $storage['render_props'] = $render_props;
     if (!isset($storage['configuration'])) {
       $storage['configuration'] = $configuration;
     }
-    $component_id = $configuration['component_id'] ?? $initial_component_id;
+    $component_id = $storage['configuration']['component_id'] ?? $configuration['component_id'] ?? $initial_component_id;
     $trigger_element = $form_state->getTriggeringElement();
+    // Handling select change.
     if ($form_state->isRebuilding()) {
-      if (isset($trigger_element['#ui_patterns']['id']) && $trigger_element['#ui_patterns']['id'] === 'component_selector') {
+      if (isset($trigger_element['#ui_patterns']['id']) && $trigger_element['#ui_patterns']['id'] === 'component_id') {
         $component_id = $form_state->getValue($trigger_element['#parents']);
         $storage['configuration']['component_id'] = $component_id;
       }
-      else {
-        $component_id = $storage['configuration']['component_id'] ?? $initial_component_id;
-      }
     }
-    $this->seComponentStorage($storage, $form_state);
+    ComponentFormBuilderState::setComponentStorage($storage, $form_state, $this->getComponentStorageSubKey());
     $form = [];
     if ($initial_component_id === NULL) {
-      $form["component_selector"] = $this->buildComponentSelectorForm(
+      $form["component_id"] = $this->expandAjax($this->buildComponentSelectorForm(
         $wrapper_id,
         $component_id
-      );
+      ), $form_state);
     }
     $form["component"] = $this->buildComponentForm(
       $wrapper_id,
@@ -252,17 +244,18 @@ trait ComponentFormBuilderTrait {
     $component_id,
     FormStateInterface $form_state
   ): array {
-    $configuration = $this->getComponentFormState('configuration', $form_state);
+    $configuration = ComponentFormBuilderState::getComponentFormState('configuration', $form_state, $this->getComponentStorageSubKey());
     $variant_id = $configuration['variant_id'] ?? NULL;
     $trigger_element = $form_state->getTriggeringElement();
     if ($form_state->isRebuilding(
-      ) && isset($trigger_element['#ui_patterns']['id']) && $trigger_element['#ui_patterns']['id'] === 'variant_selector') {
+      ) && isset($trigger_element['#ui_patterns']['id']) && $trigger_element['#ui_patterns']['id'] === 'variant_id') {
       $variant_id = $form_state->getValue($trigger_element['#parents']);
       $configuration['variant_id'] = $variant_id;
-      $this->setComponentFormState(
+      ComponentFormBuilderState::setComponentFormState(
         'configuration',
         $configuration,
-        $form_state
+        $form_state,
+        $this->getComponentStorageSubKey()
       );
     }
     $form = [
@@ -272,16 +265,15 @@ trait ComponentFormBuilderTrait {
     ];
     $variant_wrapper_id = 'ui-patterns-component-variant';
     if ($component_id !== NULL) {
-      $form['variant_selector'] = $this->buildComponentVariantSelectorForm(
+      $form['variant_id'] = $this->buildComponentVariantSelectorForm(
         $variant_wrapper_id,
         $form_state,
         $component_id,
         $variant_id
       );
-      $form['variant'] = $this->buildComponentVariantForm(
+      $form += $this->buildComponentVariantForm(
         $variant_wrapper_id,
         $component_id,
-        $variant_id,
         $form_state
       );
     }
@@ -298,7 +290,6 @@ trait ComponentFormBuilderTrait {
   private function buildComponentVariantForm(
     $wrapper_id,
     string $component_id,
-    $variant_id,
     FormStateInterface $form_state
   ): array {
     $component = $this->getComponent($component_id);
@@ -307,29 +298,29 @@ trait ComponentFormBuilderTrait {
       '#prefix' => '<div id="' . $wrapper_id . '">',
       '#suffix' => '</div>',
     ];
-    $render_slots = $this->getComponentFormState('render_slots', $form_state);
-    $render_props = $this->getComponentFormState('render_props', $form_state);
-    $configuration = $this->getComponentFormState('configuration', $form_state);
+    $render_slots = ComponentFormBuilderState::getComponentFormState('render_slots', $form_state, $this->getComponentStorageSubKey());
+    $render_props = ComponentFormBuilderState::getComponentFormState('render_props', $form_state, $this->getComponentStorageSubKey());
+    $configuration = ComponentFormBuilderState::getComponentFormState('configuration', $form_state, $this->getComponentStorageSubKey());
 
     if (!isset($configuration['props'])) {
       $configuration['props'] = [];
     }
     if (!isset($configuration['slots'])) {
-      $configuration['props'] = [];
+      $configuration['slots'] = [];
     }
 
     if ($render_slots) {
       $form['slots'] = $this->buildSlotsForm(
         $form_state,
         $component,
-        $configuration['slots']
+        $configuration['component']['slots']
       );
     }
     if ($render_props) {
       $form['props'] = $this->buildPropsForm(
         $form_state,
         $component,
-        $configuration['props']
+        $configuration['component']['props']
       );
     }
     return $form;
@@ -355,16 +346,26 @@ trait ComponentFormBuilderTrait {
       "#type" => "select",
       "#title" => t("Component"),
       "#options" => $options,
-      '#ui_patterns' => ['id' => 'component_selector'],
+      '#ui_patterns' => ['id' => 'component_id'],
       '#default_value' => $selected_component_id,
       '#ajax' => [
-        'callback' => [$this, 'buildComponentSelectorFormChangeAjax'],
+        'callback' => [ComponentFormBuilderState::class, 'changeSelectorFormChangeAjax'],
         'wrapper' => $wrapper_id,
         'effect' => 'fade',
       ],
     ];
   }
 
+  /**
+   * Returns the component form storage subkey.
+   *
+   * Plugins should overwrite this method
+   * if the same form builder form is part of the
+   */
+  protected function getComponentStorageSubKey(): string {
+    return 'default';
+  }
+
   /**
    * Build the variant select widget.
    *
@@ -372,10 +373,10 @@ trait ComponentFormBuilderTrait {
    *   The variant select.
    */
   private function buildComponentVariantSelectorForm(
-    $wrapper_id,
+    string $wrapper_id,
     FormStateInterface $form_state,
-    $component_id,
-    $default_variant_id
+    string $component_id,
+    string $default_variant_id
   ): array {
     $component = $this->getComponent($component_id);
     $definition = $component->getPluginDefinition();
@@ -386,18 +387,22 @@ trait ComponentFormBuilderTrait {
     foreach ($definition["variants"] as $variant_id => $variant) {
       $options[$variant_id] = $variant["title"];
     }
-    return [
+    $id = strtr(Html::getId('variant_id'), '-', '_');
+
+    return $this->expandAjax([
       "#type" => "select",
+      '#name' => $id,
+      '#id' => $id,
       "#title" => t("Variant"),
       "#options" => $options,
-      '#ui_patterns' => ['id' => 'variant_selector'],
+      '#ui_patterns' => ['id' => 'variant_id', 'storage_sub_key' => $this->getComponentStorageSubKey()],
       '#default_value' => $default_variant_id,
       '#ajax' => [
-        'callback' => [$this, 'buildComponentVariantSelectorFormChangeAjax'],
+        'callback' => [ComponentFormBuilderState::class, 'buildComponentVariantSelectorFormChangeAjax'],
         'wrapper' => $wrapper_id,
         'effect' => 'fade',
       ],
-    ];
+    ], $form_state);
   }
 
   /**
@@ -410,39 +415,21 @@ trait ComponentFormBuilderTrait {
     FormStateInterface $form_state
   ) {
     $form = $form['ui_patterns'];
-    $configuration = $this->getComponentFormState('configuration', $form_state);
+    $configuration = ComponentFormBuilderState::getComponentFormState('configuration', $form_state, $this->getComponentStorageSubKey());
     $configuration['props'] = [];
-    $props_form = $form['component']['variant']['props'] ?? [];
+    $props_form = $form['component']['props'] ?? [];
     $this->submitPropsForm($props_form, $form_state, $configuration['props']);
     $configuration['slots'] = [];
-    $slots_form = $form['component']['variant']['slots'] ?? [];
-    $this->submitSlotsForm($slots_form, $form_state, $configuration['slots']);
-    $this->setComponentFormState('configuration', $configuration, $form_state);
-    $this->configuration['ui_patterns'] = $configuration;
-  }
 
-  /**
-   * Ajax callback for component selector change.
-   */
-  final public function buildComponentSelectorFormChangeAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $parents = $form_state->getTriggeringElement()['#array_parents'];
-    $sub_form = NestedArray::getValue($form, array_slice($parents, 0, -1));
-    return $sub_form['component'];
-  }
-
-  /**
-   * Ajax callback for variant selector change.
-   */
-  final public function buildComponentVariantSelectorFormChangeAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $parents = $form_state->getTriggeringElement()['#array_parents'];
-    $form = NestedArray::getValue($form, array_slice($parents, 0, -1));
-    return $form['variant'];
+    $this->submitPropsForm(
+      $form['component']['props'],
+      $form_state,
+      $configuration['props']
+    );
+    $slots = isset($form['component']['slots']) ?: [];
+    $this->submitSlotsForm($slots, $form_state, $configuration['slots']);
+    ComponentFormBuilderState::setComponentFormState('configuration', $configuration, $form_state, $this->getComponentStorageSubKey());
+    $this->configuration['ui_patterns'] = $configuration;
   }
 
   /**
@@ -517,12 +504,15 @@ trait ComponentFormBuilderTrait {
             '#type' => 'submit',
             '#name' => strtr($slot_id, '-', '_') . $delta . '_remove',
             '#value' => $this->t('Delete'),
-            '#submit' => [[$this, 'removeSlotItemSubmitAjax']],
+            '#submit' => [ComponentFormBuilderState::class . '::removeSlotItemSubmitAjax'],
             '#access' => TRUE,
             '#delta' => $delta,
+            '#ui_patterns' => [
+              'storage_sub_key' => $this->getComponentStorageSubKey(),
+            ],
             '#slot_id' => $slot_id,
             '#ajax' => [
-              'callback' => [$this, 'removeSlotItemAjax'],
+              'callback' => [ComponentFormBuilderState::class, 'removeSlotItemAjax'],
               'wrapper' => $wrapper_id,
               'effect' => 'fade',
             ],
@@ -532,7 +522,8 @@ trait ComponentFormBuilderTrait {
             '#ui_patterns_header' => TRUE,
             'dropdown_actions' => [
               $this->expandComponentButton(
-                $delete_action
+                $delete_action,
+                $form_state
               ),
             ],
           ];
@@ -543,33 +534,23 @@ trait ComponentFormBuilderTrait {
       foreach ($options as $source_id => $source_label) {
         $action_buttons[$source_id] = $this->expandComponentButton([
           '#type' => 'submit',
-          '#name' => strtr(
-                                                                         $slot_id,
-                                                                         '-',
-                                                                         '_'
-          ) . $source_id . '_add_more',
-          '#value' => $this->t(
-                                                                       'Add %source',
-                                                                       ['%source' => $source_label]
-          ),
+          '#name' => strtr($slot_id, '-', '_') . $source_id . '_add_more',
+          '#value' => $this->t('Add %source', ['%source' => $source_label]),
           '#submit' => [
-                                                                       [
-                                                                         $this,
-                                                                         'addSlotItemSubmitAjax',
-                                                                       ],
+            ComponentFormBuilderState::class . '::addSlotItemSubmitAjax',
           ],
           '#access' => TRUE,
           '#slot_id' => $slot_id,
           '#source_id' => $source_id,
           '#ajax' => [
             'callback' => [
-              $this,
+              ComponentFormBuilderState::class,
               'addSlotItemAjax',
             ],
             'wrapper' => $wrapper_id,
             'effect' => 'fade',
           ],
-        ]);
+        ], $form_state);
       }
       $form[$slot_id]['add_more_button'] = $this->buildComponentDropbutton(
         $action_buttons
@@ -581,93 +562,6 @@ trait ComponentFormBuilderTrait {
     return $form;
   }
 
-  /**
-   * Ajax submit handler: Add slot item.
-   */
-  final public function addSlotItemSubmitAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $button = $form_state->getTriggeringElement();
-    $slot_id = $button['#slot_id'];
-    $source_id = $button['#source_id'];
-    $configuration = $this->getComponentFormState(
-      'configuration',
-      $form_state
-    );
-    $configuration['slots'][$slot_id]['sources'][] = ['id' => $source_id];
-    $this->setComponentFormState('configuration', $configuration, $form_state);
-    $form_state->setRebuild();
-  }
-
-  /**
-   * Ajax handler: Add slot item.
-   */
-  public function addSlotItemAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $parents = $form_state->getTriggeringElement()['#array_parents'];
-    $form = NestedArray::getValue($form, array_slice($parents, 0, -2));
-    return $form['sources'];
-  }
-
-  /**
-   * Ajax submit handler: Remove slot item.
-   */
-  final public function removeSlotItemSubmitAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $button = $form_state->getTriggeringElement();
-    $delta = $button['#delta'];
-    $slot_id = $button['#slot_id'];
-    $configuration = $this->getComponentFormState(
-      'configuration',
-      $form_state
-    );
-    unset($configuration['slots'][$slot_id]['sources'][$delta]);
-    $this->setComponentFormState('configuration', $configuration, $form_state);
-    $form_state->setRebuild();
-  }
-
-  /**
-   * Ajax handler: Remove slot item.
-   */
-  final public function removeSlotItemAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $parents = $form_state->getTriggeringElement()['#array_parents'];
-    return NestedArray::getValue($form, array_slice($parents, 0, -4));
-  }
-
-  /**
-   * Submit slots form.
-   */
-  private function submitSlotsForm(
-    array $form,
-    FormStateInterface $form_state,
-    &$configuration
-  ) {
-    $source_slots = $form_state->get('ui_patterns_slot_sources');
-    if (!isset($source_slots)) {
-      return;
-    }
-    foreach ($source_slots as $slot_id => $source_ids) {
-      foreach ($source_ids as $source_index => $source) {
-        $source->submitConfigurationForm(
-          $form[$slot_id]['sources'][$source_index],
-          $form_state
-        );
-        $configuration[$slot_id]['sources'][$source_index] = [
-          'value' => $source->getConfiguration()['form_value'],
-          'id' => $source->getPluginId(),
-        ];
-      }
-    }
-  }
-
   /**
    * Returns the source plugin manager.
    */
@@ -687,6 +581,7 @@ trait ComponentFormBuilderTrait {
     &$configuration
   ): array {
     $contexts = $this->getComponentSourceContexts();
+
     $form = [];
     $build_sources = [];
     $source_plugin_manager = $this->sourcePluginManager();
@@ -731,26 +626,20 @@ trait ComponentFormBuilderTrait {
             $button = [
               '#type' => 'submit',
               '#name' => $prop_id . '_' . strtr($source_id, '-', '_') . '_change',
-              '#value' => $source->label(),
+              '#value' => $source_id,
+              '#submit' => [ComponentFormBuilderState::class . '::changePropSubmitAjax'],
               '#source_id' => $source_id,
               '#prop_id' => $prop_id,
-              '#submit' => [
-                [
-                  $this,
-                  'changePropSubmitAjax',
-                ],
-              ],
-              '#access' => TRUE,
               '#ajax' => [
                 'callback' => [
-                  $this,
+                  ComponentFormBuilderState::class,
                   'changePropItemAjax',
                 ],
                 'wrapper' => $wrapper_id,
                 'effect' => 'fade',
               ],
             ];
-            $dropdown_actions[$source_id] = $this->expandComponentButton($button);
+            $dropdown_actions[$source_id] = $this->expandComponentButton($button, $form_state);
           }
         }
         $form[$prop_id]['source_id'] = [
@@ -772,36 +661,6 @@ trait ComponentFormBuilderTrait {
     return $form;
   }
 
-  /**
-   * Ajax submit handler: Change props type submit handler.
-   */
-  final public function changePropSubmitAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $button = $form_state->getTriggeringElement();
-    $prop_id = $button['#prop_id'];
-    $source_id = $button['#source_id'];
-    $configuration = $this->getComponentFormState(
-      'configuration',
-      $form_state
-    );
-    $configuration['props'][$prop_id]['source_id'] = $source_id;
-    $this->setComponentFormState('configuration', $configuration, $form_state);
-    $form_state->setRebuild();
-  }
-
-  /**
-   * Ajax handler: Change prop type.
-   */
-  final public function changePropItemAjax(
-    array $form,
-    FormStateInterface $form_state
-  ) {
-    $parents = $form_state->getTriggeringElement()['#array_parents'];
-    return NestedArray::getValue($form, array_slice($parents, 0, -3));
-  }
-
   /**
    * Submit props forms.
    */
@@ -811,7 +670,7 @@ trait ComponentFormBuilderTrait {
     &$configuration
   ) {
     $sources = $form_state->get('ui_patterns_prop_sources');
-    $state_configuration = $this->getComponentFormState('configuration', $form_state);
+    $state_configuration = ComponentFormBuilderState::getComponentFormState('configuration', $form_state, $this->getComponentStorageSubKey());
     foreach ($sources as $prop_id => $source) {
       $source->submitConfigurationForm(
         $form[$prop_id],
@@ -825,6 +684,32 @@ trait ComponentFormBuilderTrait {
     }
   }
 
+  /**
+   * Submit slots form.
+   */
+  private function submitSlotsForm(
+    $form,
+    FormStateInterface $form_state,
+    &$configuration
+  ):void {
+    $source_slots = $form_state->get('ui_patterns_slot_sources');
+    if (!isset($source_slots)) {
+      return;
+    }
+    foreach ($source_slots as $slot_id => $source_ids) {
+      foreach ($source_ids as $source_index => $source) {
+        $source->submitConfigurationForm(
+          $form[$slot_id]['sources'][$source_index],
+          $form_state
+        );
+        $configuration[$slot_id]['sources'][$source_index] = [
+          'value' => $source->getConfiguration()['form_value'],
+          'id' => $source->getPluginId(),
+        ];
+      }
+    }
+  }
+
   /**
    * Build component data provided to the SDC element.
    */
@@ -841,8 +726,7 @@ trait ComponentFormBuilderTrait {
     // @todo injection
     $builder = \Drupal::service('ui_patterns.component_element_builder');
     $contexts = $this->getComponentSourceContexts();
-    $build = $builder->build($component, $configuration, $contexts);
-    return $build;
+    return $builder->build($component, $configuration, $contexts);
   }
 
 }
diff --git a/src/Form/ComponentSettingsFormBuilderTrait.php b/src/Form/ComponentSettingsFormBuilderTrait.php
index dc703907f308083bbf8f27eab88c6f0c99e01e8c..4e52fd9bf645bf6d6a4d0679b88bf3334654b401 100644
--- a/src/Form/ComponentSettingsFormBuilderTrait.php
+++ b/src/Form/ComponentSettingsFormBuilderTrait.php
@@ -1,6 +1,6 @@
 <?php
 
-declare(strict_types = 1);
+declare(strict_types=1);
 
 namespace Drupal\ui_patterns\Form;
 
@@ -14,52 +14,37 @@ trait ComponentSettingsFormBuilderTrait {
   use ComponentFormBuilderTrait;
 
   /**
+   * Adapter function for plugin settings/options.
    *
-   */
-  public static function getComponentSettingsFormDefault() {
-    return [
-      "ui_patterns" => NULL,
-    ];
-  }
-
-  /**
+   * Overwrite to return settings/options of the
+   * current plugin.
    *
+   * @return mixed
+   *   The plugin settings/options.
    */
-  private function getMappedSettingsToConfig() {
-    $settings = $this->getSettings()['ui_patterns'] ?? [];
-    // Mapping the settings array saved by settingsForm to the required configuration form.
-    $configuration = [
-      'ui_patterns' => [
-        'component_id' => $settings['component_selector'] ?? NULL,
-        'variant_id' => $settings['component']['variant']['variant_selector'] ?? NULL,
-        'props' => $settings['component']['variant']['props'] ?? [],
-        'slots' => $settings['component']['variant']['slots'] ?? [],
-      ],
-    ];
-    return $configuration;
-  }
+  abstract protected function getComponentSettings(): array;
 
   /**
    * {@inheritdoc}
    */
-  protected function componentSettingsForm(array $form, FormStateInterface $form_state): array {
-
-    $configuration = $this->getMappedSettingsToConfig();
+  protected function componentSettingsForm(
+    array $form,
+    FormStateInterface $form_state
+  ): array {
     $trigger_element = $form_state->getTriggeringElement();
+    $configuration = $this->getComponentSettings()['ui_patterns'] ?? [];
     if ($form_state->isRebuilding() === FALSE
-    || (isset($trigger_element['#op']) && $trigger_element['#op'] === 'update')
+      || (isset($trigger_element['#op']) && $trigger_element['#op'] === 'update')
     ) {
-      $this->setComponentFormState('configuration', $configuration['ui_patterns'], $form_state);
+      ComponentFormBuilderState::setComponentFormState(
+        'configuration',
+        $configuration,
+        $form_state,
+        $this->getComponentStorageSubKey(),
+        FALSE
+      );
     }
     return $this->buildComponentsForm($form_state, $configuration);
   }
 
-  /**
-   *
-   */
-  final protected function buildComponentSettingsData() {
-    $configuration = $this->getMappedSettingsToConfig();
-    return $this->buildComponentData($configuration);
-  }
-
 }
diff --git a/src/Plugin/UiPatterns/Source/TextfieldWidget.php b/src/Plugin/UiPatterns/Source/TextfieldWidget.php
index cb88e65f4ade723248fab2467b823370f2a75b83..684a1c5ef1acfe6d04409f61af0468b900c47db7 100644
--- a/src/Plugin/UiPatterns/Source/TextfieldWidget.php
+++ b/src/Plugin/UiPatterns/Source/TextfieldWidget.php
@@ -15,7 +15,8 @@ use Drupal\ui_patterns\SourcePluginBase;
  *   description = @Translation("One-line text field."),
  *   prop_types = {
  *     "string",
- *     "machine_name"
+ *     "machine_name",
+ *     "slot"
  *   }
  * )
  */
diff --git a/ui_patterns.api.php b/ui_patterns.api.php
new file mode 100644
index 0000000000000000000000000000000000000000..97ac96a21d85a9353fdbdcc0b878739360754594
--- /dev/null
+++ b/ui_patterns.api.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ */
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * .UI Patterns form configuration changed.
+ *
+ * Informs contrib module if ui patterns form has changed.
+ *
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ *   The form state.
+ * @param array $configuration
+ *   The form configuration.
+ *
+ * @void
+ *
+ * @ingroup ui_patterns
+ */
+function hook_ui_patterns_form_configuration_changed(FormStateInterface $form_state, array $configuration) {
+
+}
diff --git a/ui_patterns.module b/ui_patterns.module
index db57b19754c3f1e9d382bb08ba32a58788ebd179..ff150c1c20d2d86c150e57d6594fa5a386441e23 100644
--- a/ui_patterns.module
+++ b/ui_patterns.module
@@ -1,20 +1,24 @@
 <?php
 
+/**
+ * @file
+ * Adds UI Patterns themes and UI Elements.
+ */
+
 declare(strict_types = 1);
 
 /**
  * Implements hook_theme().
  */
 function ui_patterns_theme() {
-  return array(
+  return [
     'ui_patterns_actions' => [
       'render element' => 'element',
       'template' => 'ui-patterns-actions',
     ],
-  );
+  ];
 }
 
-
 /**
  * Prepares variables for ui_patterns_actions component.
  *
@@ -40,24 +44,23 @@ function template_preprocess_ui_patterns_actions(&$variables) {
   }
 }
 
-
 /**
  * Implements hook_preprocess_HOOK() for field_multiple_value_form().
  */
 function ui_patterns_preprocess_field_multiple_value_form(&$variables) {
-  // @TODO: Move header buttons to own column.
+  // @todo Move header buttons to own column.
   /*
   if (!empty($variables['table']['#header']) && isset($variables['table']['#rows'][0])) {
-    // Find paragraph_actions and move to header.
-    // @see template_preprocess_field_multiple_value_form()
-    if (is_array($variables['table']['#rows'][0]['data'][1]) && !empty($variables['table']['#rows'][0]['data'][1]['data']['_remove']['#ui_patterns_header'])) {
-      $variables['table']['#header'][0]['data'] = [
-        'title' => $variables['table']['#header'][0]['data'],
-        'button' => $variables['table']['#rows'][0]['data'][1]['_remove']['data'],
-      ];
-      unset($variables['table']['#rows'][0]);
-    }
-      }
-  */
+  // Find paragraph_actions and move to header.
+  // @see template_preprocess_field_multiple_value_form()
+  if (is_array($variables['table']['#rows'][0]['data'][1]) && !empty($variables['table']['#rows'][0]['data'][1]['data']['_remove']['#ui_patterns_header'])) {
+  $variables['table']['#header'][0]['data'] = [
+  'title' => $variables['table']['#header'][0]['data'],
+  'button' => $variables['table']['#rows'][0]['data'][1]['_remove']['data'],
+  ];
+  unset($variables['table']['#rows'][0]);
+  }
+  }
+   */
 
 }