diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php
index b4b092c..0efdbfc 100644
--- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php
+++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php
@@ -120,9 +120,10 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem
       '#prefix' => '<div id="' . $wrapper_id . '">',
       '#suffix' => '</div>',
     ];
-    if ($form_state->getTriggeringElement()) {
+    if ($trigger = $form_state->getTriggeringElement()) {
       $parents = array_merge($element['#field_parents'], [$items->getName(), $delta]);
       $user_input = (array) NestedArray::getValue($form_state->getUserInput(), $parents);
+      $user_input['trigger_value'] = $trigger['#value'];
       $selected_variation = $this->selectVariationFromUserInput($variations, $user_input);
     }
     else {
@@ -200,11 +201,33 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem
    *   The selected variation.
    */
   protected function selectVariationFromUserInput(array $variations, array $user_input) {
-    $selected_variation = NULL;
     if (!empty($user_input)) {
+      $creator = \Drupal::service('commerce_product.variation_bulk_creator');
+      if ($all = $creator->getAllAttributesCombinations($variations)['combinations']) {
+        $trigger_name = array_search($user_input['trigger_value'], $user_input['attributes']);
+        foreach ($all as $index => $combination) {
+          if (!array_intersect_assoc($combination, [$trigger_name => $user_input['trigger_value']])) {
+            unset($all[$index]);
+          }
+          else {
+            foreach ($user_input['attributes'] as $key => $value) {
+              if (array_intersect_assoc($combination, [$key => $value])) {
+                $user_input['valid'][$key] = $value;
+              }
+            }
+          }
+        }
+        foreach ($all as $index => $combination) {
+          $merged = array_merge($combination, $user_input['valid']);
+          if ($combination == $merged) {
+            $user_input['attributes'] = $combination;
+          }
+        }
+      }
       $attributes = $user_input['attributes'];
       $first_value = current($attributes);
       $first_key = current(array_keys($attributes));
+      $selected_variation = NULL;
       foreach ($variations as $variation) {
         $values = [];
         foreach ($attributes as $field_name => $value) {
@@ -214,8 +237,7 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem
           }
         }
         if ($attributes === $values) {
-          $selected_variation = $variation;
-          break;
+          return $variation;
         }
       }
     }
@@ -235,11 +257,16 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem
    *   The attribute information, keyed by field name.
    */
   protected function getAttributeInfo(ProductVariationInterface $selected_variation, array $variations) {
+    $creator = \Drupal::service('commerce_product.variation_bulk_creator');
+    $all = $creator->getAllAttributesCombinations($variations)['combinations'];
+    $options = $creator->getAttributeFieldOptionIds(reset($variations))['options'];
+    $selected_ids = $selected_variation->getAttributeValueIds();
     $attributes = $values = [];
     $field_definitions = $this->attributeFieldManager->getFieldDefinitions($selected_variation->bundle());
     $field_map = $this->attributeFieldManager->getFieldMap($selected_variation->bundle());
     $field_names = array_column($field_map, 'field_name');
     $index = 0;
+
     foreach ($field_names as $field_name) {
       /** @var \Drupal\commerce_product\Entity\ProductAttributeInterface $attribute_type */
       $attribute_type = $this->attributeStorage->load($field_map[$index]['attribute_id']);
@@ -254,32 +281,26 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem
       // the values from variations matching the previous attribute value.
       // For 'Color' and 'Size' attributes that means getting the colors of all
       // variations, but only the sizes of variations with the selected color.
-      $callback = NULL;
-      if ($index > 0) {
-        $previous_field_name = $field_names[$index - 1];
-        $previous_field_value = $selected_variation->getAttributeValueId($previous_field_name);
-        $callback = function ($variation) use ($previous_field_name, $previous_field_value) {
-          /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */
-          return $variation->getAttributeValueId($previous_field_name) == $previous_field_value;
-        };
-      }
+      $is_id = isset($selected_ids[$field_names[$index ? $index - 1 : $index]]);
+      $previous_field_id = $is_id ? $selected_ids[$field_names[$index ? $index - 1 : $index]] : 0;
 
-      $value = $this->getAttributeValues($variations, $field_name, $callback);
-      if (!isset($values[$field_name])) {
-        $values[$field_name] = $value;
-      }
-      elseif (!in_array($values[$field_name], $value)) {
-        $values[$field_name] += $value;
+      foreach ($all as $indeks => $combination) {
+        if ($index && !in_array($previous_field_id, $combination)) {
+          unset($all[$indeks]);
+          continue;
+        }
+        if (in_array($previous_field_id, $combination) || !$index) {
+          $is_label = isset($options[$field_name][$combination[$field_name]]);
+          $label = $is_label ? $options[$field_name][$combination[$field_name]] : '';
+          $label = empty($label) && $label != '0' ? '???' : $label;
+          $values[$field_name][$combination[$field_name]] = $label;
+        }
       }
+
       $attributes[$field_name]['values'] = $values[$field_name];
       $index++;
     }
 
-    // Filter out attributes with no values.
-    $attributes = array_filter($attributes, function ($attribute) {
-      return !empty($attribute['values']);
-    });
-
     return $attributes;
   }
 
