VariantSelect

A variant picker for valid product combinations such as color, size and availability-dependent choices.

Import
the javascript logo
import { VariantSelect } from "@schukai/monster/source/components/form/variant-select.mjs";
Source
the git logo
Package
the npm logo
Since
4.64.0

Introduction

The Monster VariantSelect helps users choose only valid option combinations. Use it for products or configurable entities where one choice changes which remaining variants are available.

When to use VariantSelect

  • Use it for dependent variant combinations: Color, size, material or region-specific availability are common examples.
  • Use it when invalid combinations must be prevented: The control can guide users toward valid choices.
  • Do not use it for independent fields: If options do not affect each other, separate controls are simpler.

Typical mistakes

Keep the variant data contract consistent. If availability, labels and selected values drift apart, users end up seeing impossible or misleading combinations.

Button Layout

Basic button-based variant selection for two dimensions.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-buttons');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S' },
    { id: 'sku-2', color: 'Red', size: 'M' },
    { id: 'sku-3', color: 'Blue', size: 'S' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' }
]);

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-buttons');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S' },
    { id: 'sku-2', color: 'Red', size: 'M' },
    { id: 'sku-3', color: 'Blue', size: 'S' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' }
]);

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-buttons"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Row Selects

Per-dimension selects for color, size, and fit using features.rowSelects.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-row');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S', fit: 'Regular' },
    { id: 'sku-2', color: 'Red', size: 'M', fit: 'Regular' },
    { id: 'sku-3', color: 'Blue', size: 'S', fit: 'Slim' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' },
    { key: 'fit', label: 'Fit' }
]);

control.setOption('features.rowSelects', true);

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-row');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S', fit: 'Regular' },
    { id: 'sku-2', color: 'Red', size: 'M', fit: 'Regular' },
    { id: 'sku-3', color: 'Blue', size: 'S', fit: 'Slim' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' },
    { key: 'fit', label: 'Fit' }
]);

control.setOption('features.rowSelects', true);

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-row"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Combined Select

Combined select with all variants. Uses a custom label template for the dropdown.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-combined');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S' },
    { id: 'sku-2', color: 'Red', size: 'M' },
    { id: 'sku-3', color: 'Blue', size: 'S' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' }
]);

control.setOption('features.rowSelects', true);
control.setOption('features.combinedSelect', true);
control.setOption('layout.combineSelect', true);
control.setOption('mapping.labelTemplate', '${id} - ${color} / ${size}');

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-combined');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S' },
    { id: 'sku-2', color: 'Red', size: 'M' },
    { id: 'sku-3', color: 'Blue', size: 'S' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' }
]);

control.setOption('features.rowSelects', true);
control.setOption('features.combinedSelect', true);
control.setOption('layout.combineSelect', true);
control.setOption('mapping.labelTemplate', '${id} - ${color} / ${size}');

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-combined"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Label Templates

Separate keys from display labels using valueTemplate and labelTemplate per dimension.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-label-template');

control.setOption('data', [
    { id: 'sku-1', colorKey: 'red', colorLabel: 'Rot', sizeKey: 's', sizeLabel: 'Small' },
    { id: 'sku-2', colorKey: 'red', colorLabel: 'Rot', sizeKey: 'm', sizeLabel: 'Medium' },
    { id: 'sku-3', colorKey: 'blue', colorLabel: 'Blau', sizeKey: 's', sizeLabel: 'Small' }
]);

control.setOption('dimensions', [
    {
        key: 'colorKey',
        label: 'Farbe',
        valueTemplate: '${colorKey}',
        labelTemplate: '${colorLabel}'
    },
    {
        key: 'sizeKey',
        label: 'Grosse',
        valueTemplate: '${sizeKey}',
        labelTemplate: '${sizeLabel}'
    }
]);

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-label-template');

control.setOption('data', [
    { id: 'sku-1', colorKey: 'red', colorLabel: 'Rot', sizeKey: 's', sizeLabel: 'Small' },
    { id: 'sku-2', colorKey: 'red', colorLabel: 'Rot', sizeKey: 'm', sizeLabel: 'Medium' },
    { id: 'sku-3', colorKey: 'blue', colorLabel: 'Blau', sizeKey: 's', sizeLabel: 'Small' }
]);

control.setOption('dimensions', [
    {
        key: 'colorKey',
        label: 'Farbe',
        valueTemplate: '${colorKey}',
        labelTemplate: '${colorLabel}'
    },
    {
        key: 'sizeKey',
        label: 'Grosse',
        valueTemplate: '${sizeKey}',
        labelTemplate: '${sizeLabel}'
    }
]);

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-label-template"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Values Map

Map raw values to labels with the values object per dimension.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-values-map');

control.setOption('data', [
    { id: 'sku-1', color: 'red', size: 's' },
    { id: 'sku-2', color: 'red', size: 'm' },
    { id: 'sku-3', color: 'blue', size: 's' }
]);

control.setOption('dimensions', [
    {
        key: 'color',
        label: 'Color',
        values: {
            blue: 'Blue',
            red: 'Red'
        }
    },
    {
        key: 'size',
        label: 'Size',
        values: {
            s: 'Small',
            m: 'Medium'
        }
    }
]);

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-values-map');

control.setOption('data', [
    { id: 'sku-1', color: 'red', size: 's' },
    { id: 'sku-2', color: 'red', size: 'm' },
    { id: 'sku-3', color: 'blue', size: 's' }
]);

control.setOption('dimensions', [
    {
        key: 'color',
        label: 'Color',
        values: {
            blue: 'Blue',
            red: 'Red'
        }
    },
    {
        key: 'size',
        label: 'Size',
        values: {
            s: 'Small',
            m: 'Medium'
        }
    }
]);

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-values-map"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Messages Off

Disable status messages with features.messages.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-messages-off');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S' },
    { id: 'sku-2', color: 'Red', size: 'M' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' }
]);

control.setOption('features.messages', false);

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-messages-off');

control.setOption('data', [
    { id: 'sku-1', color: 'Red', size: 'S' },
    { id: 'sku-2', color: 'Red', size: 'M' }
]);

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' }
]);

control.setOption('features.messages', false);

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-messages-off"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Remote Data

Load variants from /assets/examples/variants.json and map the response with mapping.selector.

Javascript

import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-remote');

control.setOption('url', '/assets/examples/variants.json');
control.setOption('mapping.selector', 'items');
control.setOption('mapping.valueTemplate', '${id}');
control.setOption('mapping.labelTemplate', '${id} - ${color} / ${size}');

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' },
    { key: 'fit', label: 'Fit' }
]);

control.refresh();<script type="module">import '@schukai/monster/source/components/form/variant-select.mjs';

const control = document.getElementById('variant-select-remote');

control.setOption('url', '/assets/examples/variants.json');
control.setOption('mapping.selector', 'items');
control.setOption('mapping.valueTemplate', '${id}');
control.setOption('mapping.labelTemplate', '${id} - ${color} / ${size}');

control.setOption('dimensions', [
    { key: 'color', label: 'Color' },
    { key: 'size', label: 'Size' },
    { key: 'fit', label: 'Fit' }
]);

control.refresh();</script>

HTML

<monster-variant-select id="variant-select-remote"></monster-variant-select>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Component Design

The control renders rows for each dimension and optionally a combined select. Styling hooks are exposed via exported parts for the container and message area.

  • control: Main wrapper of the variant select.
  • rows: Container for dimension rows.
  • row: Single dimension row.
  • message: Status message area.
monster-variant-select::part(control) {
    padding: 0.5rem;
}

monster-variant-select::part(message) {
    font-size: 0.9rem;
}

HTML Structure

<monster-variant-select></monster-variant-select>

JavaScript Initialization

const element = document.createElement('monster-variant-select');
document.body.appendChild(element);

Exported

VariantSelect

Derived from

CustomControl

Options

The Options listed in this section are defined directly within the class. This class is derived from several parent classes, including the CustomElement class. Therefore, it inherits Options from these parent classes. If you cannot find a specific Options in this list, we recommend consulting the documentation of the CustomControl.

Option
Type
Default
Description
dimensions
array<object>
undefined
Dimension definitions ({key, label, presentation, valueTemplate, labelTemplate})
dimensions.values
array<object>|object|null
undefined
Optional label map for a dimension
data
array<object>
undefined
Variant items
url
string|null
Endpoint to fetch variants
fetch
object
Fetch options (method, headers, body)
mapping
object
Data mapping for fetched results
mapping.selector
string
*
hed data
mapping.valueTemplate
string
Template for variant value
mapping.labelTemplate
string
Template for combined variant label
mapping.filter
function|null
Filter function
layout
object
Layout options
layout.autoSelect
boolean
true
do not fit
layout.buttonMinWidth
number
84
imate button layout
features
object
Feature toggles
features.messages
boolean
true
messages
object
undefined
Message text
messages.valid
string
undefined
Message for valid selection
messages.invalid
string
undefined
Message for invalid selection
messages.incomplete
string
undefined
Message for incomplete selection
actions
object
Callback actions
actions.onchange
function
called on any selection change
actions.onvalid
function
called when a valid variant is selected
actions.oninvalid
function
called when selection becomes invalid
actions.onlazyload
function
called before fetching variants
actions.onlazyloaded
function
called after fetching variants
actions.onlazyerror
function
called on fetch errors
classes
object
CSS classes
classes.option
string
monster-button-outline-primary
Base class for option buttons
classes.optionSelected
string
is-selected
Class for selected options
classes.optionDisabled
string
is-disabled
Class for disabled options

  • since
  • deprecated

Properties and Attributes

The Properties and Attributes listed in this section are defined directly within the class. This class is derived from several parent classes, including the CustomElement class and ultimately from HTMLElement. Therefore, it inherits Properties and Attributes from these parent classes. If you cannot find a specific Properties and Attributes in this list, we recommend consulting the documentation of the CustomControl.

  • data-monster-options: Sets the configuration options for the collapse component when used as an HTML attribute.
  • data-monster-option-[name]: Sets the value of the configuration option [name] for the collapse component when used as an HTML attribute.

Methods

The methods listed in this section are defined directly within the class. This class is derived from several parent classes, including the CustomElement class and ultimately from HTMLElement. Therefore, it inherits methods from these parent classes. If you cannot find a specific method in this list, we recommend consulting the documentation of the CustomControl.

Behavioral methods

refresh()
Reload the data from data or url.

State query methods

value()
Returns
  • {string|null}
value(value)
Parameters
  • value {string|null}: value

Static methods

[instanceSymbol]()
Returns
  • {symbol}
This method is called by the instanceof operator.
formAssociated()
Returns
  • {boolean}
getCSSStyleSheet()
Returns
  • {CSSStyleSheet[]}
getTag()
Returns
  • {string}

Lifecycle methods

Lifecycle methods are called by the environment and are usually not intended to be called directly.

[assembleMethodSymbol]()
Returns
  • {VariantSelect}

Events

The component emits the following events:

  • monster-variant-select-change
  • monster-variant-select-valid
  • monster-variant-select-invalid
  • monster-variant-select-lazy-load
  • monster-variant-select-lazy-loaded
  • monster-variant-select-lazy-error

For more information on how to handle events, see the mdn documentation.

The current width of the area is too small to display the content correctly.