Change a Radio Options Group to a Button Bar

Hi All,

This might be useful to someone.

Change the normal Horizontal Radio Options Group that looks like this which I have based off an Enum.

image

To a Button Bar that looks like this.

image

Extend the Halo theme. Then in the halo-ext.scss add the style shown below.

  .radio-button-bar {
    display: inline-block;
    border-radius: 10px;
    overflow: hidden;

    position:relative;
    text-align:center;
    white-space:nowrap;
    outline:0;

    color:#191919;
    font-weight:500;
    border:1px solid #c5c5c5;
    border-top-color:#c5c5c5;
    border-bottom-color:#bcbcbc;
    background-color:#fafafa;
    background-image:-webkit-linear-gradient(top,#fafafa 2%,#efefef 98%);
    background-image:linear-gradient(to bottom,#fafafa 2%,#efefef 98%);
    -webkit-box-shadow:inset 0 1px 0 white,inset 0 -1px 0 #e7e7e7,0 2px 3px rgba(0,0,0,0.05);
    box-shadow:inset 0 1px 0 white,inset 0 -1px 0 #e7e7e7,0 2px 3px rgba(0,0,0,0.05);
    text-shadow:0 1px 0 rgba(255,255,255,0.05);

    .v-select-option {
      margin: 0 0 0 0 !important;
      padding: 0 0 0 0 !important;
    }

    input[type=radio] {
      position: absolute;
      visibility: hidden;
      display: none;

      &:checked ~ label:after {
        visibility: hidden !important;
        display: none !important;
        color: transparent !important;
      }

      & ~ label:after {
        visibility: hidden !important;
        display: none !important;
        color: transparent !important;
      }

      & ~ label:before {
        visibility: hidden !important;
        display: none !important;
        content: none;
      }
    }
    label {
      padding:5px 13px;
    }

    input[type=radio]:checked + label{
      background-color:rgba(125,125,125,0.2)
    }

    span + span {
      label {
        border-left: 1px solid #c5c5c5;
      }
    }
  }

In the OptionsGroup component you need to set the stylename to radio-button-bar

That should be it.

I don’t claim to be any good at CSS in fact I’ve hardly done any at all ever. If anyone can improve on it then please share.

4 Likes

Hi,

Thank you for your topic. In addition to your styles, here is another version:

.v-select-optiongroup-button-switcher {

  @include valo-optiongroup-horizontal;

  .v-select-option {
    margin: 0;
    padding-left: 0;
  }

  .v-select-option > input {

    $checked-text-color: #f9f0ef;

    &:checked ~ label {
      color: $checked-text-color;
      @include valo-border-with-gradient($border: $v-border, $color: $v-focus-color, $gradient: $v-gradient);
      @include valo-gradient($v-focus-color, $v-gradient);
      @include box-shadow(valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $background-color: $v-focus-color, $gradient: $v-gradient));
    }

    & ~ label:after,
    &:checked ~ label:after {
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      border-radius: 0;
      border: 1px solid;
      background-color: transparent;
    }

    &:checked:hover ~ label:after {
      @include valo-button-hover-style($background-color: $v-focus-color);
    }

    &:checked:focus ~ label:after {
      $focus-style: inset 0px 0px 3px 1px rgba($checked-text-color, 0.5);
      @include box-shadow($focus-style);
    }

    &:checked:active ~ label:after {
      @include valo-button-active-style($background-color: $v-focus-color);
    }

    &:hover ~ label:after {
      @include valo-button-hover-style($background-color: $v-background-color);
    }

    &:focus ~ label:after {
      @include valo-button-focus-style();
    }

    &:active ~ label:after {
      @include valo-button-active-style($background-color: $v-background-color);
    }

    $padding-height: 6px;
    $padding-width: round($v-unit-size/2.4) + round($v-border-radius/3);
    $border-width: first-number($v-border);
    $height: $v-unit-size - 2 * $padding-height - 2 * $border-width;

    & ~ label {
      height: $height;
      padding: $padding-height $padding-width;
      border-radius: 0;
      @include valo-border-with-gradient($border: $v-border, $color: $v-background-color, $gradient: $v-gradient);
      @include valo-gradient($v-background-color, $v-gradient);
      @include box-shadow(valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $background-color: $v-background-color, $gradient: $v-gradient));
    }

    & ~ label:before {
      display: none;
    }
  }

  .v-select-option:first-child,
  .v-select-option:last-child {
    margin: 0;
  }

  .v-select-option:first-child > input {
    & ~ label {
      border-top-left-radius: $v-border-radius;
      border-bottom-left-radius: $v-border-radius;

      &:after {
        border-top-left-radius: $v-border-radius;
        border-bottom-left-radius: $v-border-radius;
      }
    }
  }

  .v-select-option:last-child > input {
    & ~ label {
      border-top-right-radius: $v-border-radius;
      border-bottom-right-radius: $v-border-radius;

      &:after {
        border-top-right-radius: $v-border-radius;
        border-bottom-right-radius: $v-border-radius;
      }
    }
  }

  .v-checkbox>input ~ label:after {
    content: "";
  }
}

the result:

image

2 Likes

Hi Gleb
I have copy-pasted to helo-ext file to use but getting an error as attached.
style error.txt (6.2 KB)

Hi, @mortozakhan

Unfortunately, your stack trace is incomplete, but I suppose that you placed the halo-switcher-button-style mixin within another mixin (in the halo-ext, I presume). So, the result styles should look like below:

@mixin com_company_sales-halo-ext {
  .v-select-optiongroup-button-switcher {
  ...
  }
}

@mixin halo-switcher-button-style($background-color: $v-background-color) {
  @include valo-border-with-gradient($border: $v-border, $color: $background-color, $gradient: $v-gradient);
  @include valo-gradient($background-color, $v-gradient);
  @include box-shadow(valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $background-color: $background-color, $gradient: $v-gradient));
}

An additional mixin is used to prevent copying of a similar code which only requires different input parameter.

Anyway, I’ve updated my post and removed additional mixin.

Regards,
Gleb

Thanks Gleb. Now the exception is gone but i might have done something wrong, its not working. Here is how I have done

  1. hello-ext3
@mixin com_company-halo-ext3 {
 
    .v-select-optiongroup-button-switcher { .....} 
  1. styles.scss
.halo {
  @include com_company-halo-ext;
  @include com_company-halo-ext2;
  @include com_company-halo-ext3;
}
  1. used the style in controller
    public Component generateOptionsGroupApplicantCategoryField(Datasource datasource, String fieldId) {
        OptionsGroup optionsGroup = componentsFactory.createComponent(OptionsGroup.class);
        optionsGroup.setOrientation(OptionsGroup.Orientation.HORIZONTAL);
        optionsGroup.setDatasource(datasource, fieldId);
        optionsGroup.setStyleName("optiongroup-button-switcher");   //select-optiongroup-button-switcher
        return optionsGroup;
    }

You need to set button-switcher.

Thank you Gleb. It worked!

Hi @gorelov, your mixin looks nice, but I wonder if you already implemented a version for the hover theme, or maybe it’s already in the official sources but it’s undocumented?

Thx
Paolo

Hi, @pfurini,

We have no plans to include the above styles in the framework, but I found that the styles are broken for the 6.10 version, so here is the updated version that also works for the hover theme:

.v-select-optiongroup-button-switcher {

    @include valo-optiongroup-horizontal;

    .v-radiobutton.v-select-option {
      margin: 0;
      padding-left: 0;
    }

    .v-radiobutton.v-select-option > input {

      &:checked ~ label {
        @include valo-button-style($background-color: $v-focus-color, $unit-size: null);
      }

      & ~ label:after,
      &:checked ~ label:after {
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        border-radius: 0;
        border: 1px solid;
        background-color: transparent;
      }

      &:checked:hover ~ label:after {
        @include valo-button-hover-style($background-color: $v-focus-color);
      }

      &:checked:focus ~ label:after {
        $checked-text-color: valo-font-color($v-focus-color, 0.9);
        $focus-style: inset 0px 0px 3px 1px rgba($checked-text-color, 0.5);
        @include box-shadow($focus-style);
      }

      &:checked:active ~ label:after {
        @include valo-button-active-style($background-color: $v-focus-color);
      }

      &:hover ~ label:after {
        @include valo-button-hover-style($background-color: $v-background-color);
      }

      &:focus ~ label:after {
        @include valo-button-focus-style();
      }

      &:active ~ label:after {
        @include valo-button-active-style($background-color: $v-background-color);
      }

      $padding-height: 6px;
      $padding-width: round($v-unit-size/2.4) + round($v-border-radius/3);
      $border-width: first-number($v-border);
      $height: $v-unit-size - 2 * $padding-height - 2 * $border-width;

      & ~ label {
        height: $height;
        padding: $padding-height $padding-width;
        border-radius: 0;
        @include valo-border-with-gradient($border: $v-border, $color: $v-background-color, $gradient: $v-gradient);
        @include valo-gradient($v-background-color, $v-gradient);
        @include box-shadow(valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $background-color: $v-background-color, $gradient: $v-gradient));
      }

      & ~ label:before {
        display: none;
      }
    }

    .v-radiobutton.v-select-option:first-child,
    .v-radiobutton.v-select-option:last-child {
      margin: 0;
    }

    .v-radiobutton.v-select-option:first-child > input {
      & ~ label {
        border-top-left-radius: $v-border-radius;
        border-bottom-left-radius: $v-border-radius;

        &:after {
          border-top-left-radius: $v-border-radius;
          border-bottom-left-radius: $v-border-radius;
        }
      }
    }

    .v-radiobutton.v-select-option:last-child > input {
      & ~ label {
        border-top-right-radius: $v-border-radius;
        border-bottom-right-radius: $v-border-radius;

        &:after {
          border-top-right-radius: $v-border-radius;
          border-bottom-right-radius: $v-border-radius;
        }
      }
    }

    .v-checkbox > input ~ label:after {
      content: "";
    }
  }

As for the 7.0 version, I think that it’s better to style the new RadioButtonGroup component, so I’ll provide them later.

Regards,
Gleb

5 Likes

It appears that the above styles are applicable to the new radioButtonGroup component which is introduced in version 7.0.