The PHP Code
function bmwp_color_variation_buttons( $html, $args ) {
// Extract array elements into variables
$options = $args[ 'options' ];
$product = $args[ 'product' ];
$attribute = $args[ 'attribute' ];
$name = $args[ 'name' ] ? $args[ 'name' ] : 'attribute_' . sanitize_title( $attribute );
$id = $args[ 'id' ] ? $args[ 'id' ] : sanitize_title( $attribute );
$class = $args[ 'class' ];
if( empty( $options ) || ! $product || !$product->is_type( 'variable' ) ) {
return $html;
}
// Define button settings based on attribute
$button_settings = [
'pa_color' => [
'class' => 'bmwp-color-button',
'container' => 'bmwp-color-variations',
'get_style' => function( $term ) {
$color_image_url = get_term_meta( $term->term_id, 'color_image', true );
$color = $color_image_url ? $color_image_url : get_term_meta( $term->term_id, 'color_color', true );
return $color_image_url ? "background-image: url('{$color_image_url}');" : "background-color: {$color};";
},
'display' => ''
],
'pa_size' => [
'class' => 'bmwp-size-button',
'container' => 'bmwp-size-variations',
'get_style' => function( $term ) { return ''; },
'display' => function( $term ) { return esc_html( $term->name ); }
],
'pa_extra-essence' => [
'class' => 'bmwp-essence-button',
'container' => 'bmwp-essence-variations',
'get_style' => function( $term ) { return ''; },
'display' => function( $term ) { return esc_html( $term->name ); }
],
];
// Check if the attribute is in our settings
if ( isset( $button_settings[ $attribute ] ) ) {
$settings = $button_settings[ $attribute ];
$selected_value = isset( $args['selected']) ? $args['selected'] : '';
$terms = wc_get_product_terms( $product->get_id(), $attribute, array('fields' => 'all') );
if ( ! empty( $terms ) ) {
$buttons = '<div class="' . esc_attr( $settings['container'] ) . '">';
foreach ( $terms as $term ) {
$term_name = esc_html( $term->name );
$term_slug = esc_attr( $term->slug );
$selected_class = ( $selected_value === $term_slug ) ? 'selected' : '';
$style = call_user_func( $settings['get_style'], $term );
$display = $settings['display'] ? call_user_func( $settings['display'], $term ) : '';
$buttons .= sprintf(
'<button type="button" class="%1$s %2$s" data-attribute_name="attribute_%3$s" data-value="%4$s" title="%5$s" style="%6$s">%7$s</button>',
esc_attr( $settings['class'] ),
$selected_class,
esc_attr( $attribute ),
$term_slug,
$term_name,
$style,
$display
);
}
$buttons .= '</div>';
return $html . $buttons;
}
}
return $html;
}
add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'bmwp_color_variation_buttons', 20, 2 );
The JavaScript Code
document.addEventListener('DOMContentLoaded', function() {
// Generic function to handle button clicks
function handleButtonClick(buttonClass, variationClass) {
document.querySelectorAll(buttonClass).forEach(function(button) {
button.addEventListener('click', function() {
const attributeName = button.getAttribute('data-attribute_name');
const attributeValue = button.getAttribute('data-value');
// Update the corresponding select dropdown
const selectElement = document.querySelector('select[name="' + attributeName + '"]');
if (selectElement) {
selectElement.value = attributeValue;
const event = new Event('change', { bubbles: true });
selectElement.dispatchEvent(event);
}
// Update the selected state of the buttons
const variationContainer = button.closest(variationClass);
if (variationContainer) {
variationContainer.querySelectorAll(buttonClass).forEach(function(btn) {
btn.classList.remove('selected');
});
button.classList.add('selected');
}
});
});
}
// Apply the function to different button types
handleButtonClick('.bmwp-color-button', '.bmwp-color-variations');
handleButtonClick('.bmwp-size-button', '.bmwp-size-variations');
handleButtonClick('.bmwp-essence-button', '.bmwp-essence-variations');
});
The CSS code
Please be sure that you have disabled the select element and you have properly display and positioning the new buttons you have created. Enjoy!
select#pa_size,
select#pa_color {
display: none;
}
.bmwp-color-variations,
.bmwp-size-variations,
.bmwp-essence-variations {
display: flex;
gap: 5px;
flex-wrap: wrap;
}
.bmwp-color-button {
width: 38px;
height: 38px;
padding: 3px;
border-radius: 100px;
border: 2px solid #929294;
cursor: pointer;
background-size: cover;
background-position: center;
background-clip: content-box; /* Ensure the background stays within the padding area */
box-sizing: border-box; /* Include padding and border in the element's width and height */
position: relative;
}
/* Highlight the selected color */
.bmwp-color-button.selected {
border-color: var(--contrast-alt)!important;
}
/* Tooltip styling */
.bmwp-color-button::before {
content: attr(title); /* Use the title attribute for the tooltip text */
position: absolute;
bottom: calc(100% + 10px); /* Position the tooltip above the button */
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 5px;
border-radius: 5px;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
font-size: 12px;
z-index: 1000;
}
.bmwp-color-button:hover::before {
opacity: 1;
visibility: visible;
}
.bmwp-color-button::after {
content: '';
position: absolute;
bottom: 100%; /* Position it at the bottom of the tooltip */
left: 50%;
transform: translateX(-50%);
border-width: 5px;
border-style: solid;
border-color: #333 transparent transparent transparent;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
z-index: 1000;
}
/* Show the tooltip arrow on hover */
.bmwp-color-button:hover::after {
opacity: 1;
visibility: visible;
}