diff --git a/src/ComponentPluginManager.php b/src/ComponentPluginManager.php
index 627101e45e2719079a2123e97ccb6ddd2ed81b11..f9f5eb49e8da760d96cda3badb016bcacdadab1b 100644
--- a/src/ComponentPluginManager.php
+++ b/src/ComponentPluginManager.php
@@ -125,6 +125,9 @@ class ComponentPluginManager extends SdcPluginManager implements CategorizingPlu
     if (!isset($definition['props']['properties'])) {
       return $definition;
     }
+    if (isset($definition["variants"])) {
+      $definition['props']['properties']['variant'] = $this->buildVariantProp($definition);
+    }
     foreach ($definition['props']['properties'] as $prop_id => $prop) {
       $definition["title"] = $definition["title"] ?? $prop_id;
       $prop_type = $this->propTypePluginManager->guessFromSchema($prop);
@@ -163,10 +166,25 @@ class ComponentPluginManager extends SdcPluginManager implements CategorizingPlu
         $definition['slots'][$slot_id] = $slot;
       }
     }
-
     return $definition;
   }
 
+  private function buildVariantProp(array $definition): array {
+    $enums = [];
+    $meta_enums = [];
+    foreach ($definition["variants"] as $variant_id => $variant) {
+      $enums[] = $variant_id;
+      $meta_enums[$variant_id] = $variant['title'] ?? $variant_id;
+    }
+    return [
+      'title' => 'Variant',
+      'type' => 'string',
+      '$ref' => "ui-patterns://variant",
+      'enum' => $enums,
+      'meta:enum' => $meta_enums
+    ];
+  }
+
   /**
    * Finds assets related to the provided metadata file.
    *
diff --git a/src/Element/ComponentElementBuilder.php b/src/Element/ComponentElementBuilder.php
index 13f8138f690dca98bd25f21c8e6cbcbb4530f060..470d167b2856f67604773d59a4b3f51508e7df53 100644
--- a/src/Element/ComponentElementBuilder.php
+++ b/src/Element/ComponentElementBuilder.php
@@ -57,12 +57,14 @@ class ComponentElementBuilder implements TrustedCallbackInterface {
   protected function buildProps(array $build, Component $component, array $configuration, array $contexts): array {
     $props = $component->metadata->schema['properties'] ?? [];
     foreach ($props as $prop_id => $prop_definition) {
-      $prop_configuration = $configuration['props'][$prop_id] ?? [];
+      if ($prop_id === 'variant') {
+        $prop_configuration = $configuration['variant_id'] ?? [];
+      }
+      else {
+        $prop_configuration = $configuration['props'][$prop_id] ?? [];
+      }
       $build = $this->buildProp($build, $prop_id, $prop_definition, $prop_configuration, $contexts);
     }
-    if (isset($configuration["variant_id"])) {
-      $build['#props']["variant"] = $configuration["variant_id"];
-    }
     return $build;
   }
 
diff --git a/src/Element/ComponentForm.php b/src/Element/ComponentForm.php
index ec72a73215b12d0e0b3fdef23c08272c8b4150dc..ec72bdb562753a598630d47bce9f7285dda9a1f0 100644
--- a/src/Element/ComponentForm.php
+++ b/src/Element/ComponentForm.php
@@ -146,10 +146,13 @@ class ComponentForm extends ComponentFormBase {
     if (!$component_id) {
       return $element;
     }
-    $element['variant_id'] = self::buildComponentVariantSelectorForm(
-      $element,
-      $element['#default_value']['variant_id'] ?? NULL,
-    );
+    $component = static::getComponent($element);
+    if (isset($component->metadata->schema['properties']['variant'])) {
+      $element['variant_id'] = self::buildComponentVariantSelectorForm(
+        $component_id,
+        $element['#default_value']['variant_id'] ?? NULL,
+      );
+    }
     $element['slots'] = self::buildSlotsForm($element, $component_id);
     $element['props'] = self::buildPropsForm($element, $component_id);
   }
@@ -195,22 +198,15 @@ class ComponentForm extends ComponentFormBase {
    *   The variant select.
    */
   private static function buildComponentVariantSelectorForm(
-    array $element,
-    string|NULL $default_variant_id,
+    string $component_id,
+    array|NULL $default_variant_id,
   ): array {
-    $component = static::getComponent($element);
-    $definition = $component->getPluginDefinition();
-    if (!isset($definition["variants"])) {
-      return [];
-    }
-    $options = [];
-    foreach ($definition["variants"] as $variant_id => $variant) {
-      $options[$variant_id] = $variant["title"] ?? $variant_id;
-    }
+
     return [
-      "#type" => "select",
+      "#type" => "component_prop_form",
       "#title" => t("Variant"),
-      "#options" => $options,
+      "#component_id" => $component_id,
+      "#prop_id" => 'variant',
       '#default_value' => $default_variant_id,
     ];
   }
diff --git a/src/Element/ComponentPropsForm.php b/src/Element/ComponentPropsForm.php
index 61851c7c19317e1c61cb7dd74b6f0065c956a5b3..c0a8668a8559d3ed9063f8b390f1b712cde00ca7 100644
--- a/src/Element/ComponentPropsForm.php
+++ b/src/Element/ComponentPropsForm.php
@@ -73,6 +73,9 @@ class ComponentPropsForm extends ComponentFormBase {
     }
     $configuration = $element['#default_value']['props'] ?? [];
     foreach ($props as $prop_id => $prop) {
+      if ($prop_id === 'variant') {
+        continue;
+      }
       $prop_type = $prop['ui_patterns']['type_definition'];
       $element[$prop_id] = [
         '#type' => 'component_prop_form',
diff --git a/src/Plugin/UiPatterns/PropType/VariantPropType.php b/src/Plugin/UiPatterns/PropType/VariantPropType.php
new file mode 100644
index 0000000000000000000000000000000000000000..8de4a9a02c9d7ca3b383d5b6d83d83046a57a3fa
--- /dev/null
+++ b/src/Plugin/UiPatterns/PropType/VariantPropType.php
@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\ui_patterns\Plugin\UiPatterns\PropType;
+
+use Drupal\Component\Render\MarkupInterface;
+use Drupal\Core\Render\RenderableInterface;
+use Drupal\ui_patterns\PropTypePluginBase;
+
+/**
+ * Provides a 'Variant' PropType.
+ *
+ * @PropType(
+ *   id = "variant",
+ *   label = @Translation("Variant"),
+ *   description = @Translation("Prop Type for component variants."),
+ *   priority = 10,
+ *   default_source = "select",
+ *   schema = {
+ *   },
+ * )
+ */
+class VariantPropType extends PropTypePluginBase {
+
+}
diff --git a/src/Plugin/UiPatterns/Source/SelectWidget.php b/src/Plugin/UiPatterns/Source/SelectWidget.php
index 47b6158c5ea1229367b1a602f50e4a507f8486e3..2f4d07a1aa1ea61f086f1184d4b99eca427b54e1 100644
--- a/src/Plugin/UiPatterns/Source/SelectWidget.php
+++ b/src/Plugin/UiPatterns/Source/SelectWidget.php
@@ -15,7 +15,8 @@ use Drupal\ui_patterns\SourcePluginPropValue;
  *   label = @Translation("Select"),
  *   description = @Translation("A drop-down menu or scrolling selection box."),
  *   prop_types = {
- *     "enum"
+ *     "enum",
+ *     "variant"
  *   },
  *   tags = { "widget" }
  * )
diff --git a/tests/modules/ui_patterns_test/components/card/card.component.yml b/tests/modules/ui_patterns_test/components/card/card.component.yml
index f47288a7205cb3229c11d0ac9a1adc9312c47356..cdbf92f97f56f61bc98f01097fe484e571160773 100644
--- a/tests/modules/ui_patterns_test/components/card/card.component.yml
+++ b/tests/modules/ui_patterns_test/components/card/card.component.yml
@@ -9,9 +9,9 @@ icon_map:
   - [rectangle_vertical, square_four, square_five]
 variants:
   default:
-    title: "Default"
+    title: "Default title"
   horizontal:
-    title: "Horizontal"
+    title: "Horizontal title"
 props:
   type: object
   properties:
diff --git a/tests/modules/ui_patterns_test/components/card/card.twig b/tests/modules/ui_patterns_test/components/card/card.twig
index 0f806b25a3d3295a4d1d1a10b83841fc48bc2e15..cea6299fdc2fcb90c8f7e3b7ff7ebb1c5fa61c6f 100644
--- a/tests/modules/ui_patterns_test/components/card/card.twig
+++ b/tests/modules/ui_patterns_test/components/card/card.twig
@@ -1,4 +1,5 @@
 {% set attributes = (variant and variant|lower != 'default') ? attributes.addClass('card--' ~ variant) : attributes %}
+Variant: {{ variant }}
 <div{{ attributes.addClass('card') }}>
   {% if image and image_position != 'bottom' %}
     {{ image|add_class('card-img-top') }}