Skip to content

Instantly share code, notes, and snippets.

@iErik
Created March 18, 2019 20:03
Show Gist options
  • Select an option

  • Save iErik/ac726b5f7d904f1f3045099d852d3e03 to your computer and use it in GitHub Desktop.

Select an option

Save iErik/ac726b5f7d904f1f3045099d852d3e03 to your computer and use it in GitHub Desktop.
<template>
<c-input-container v-bind="$attrs" class="c-radio-button">
<p v-if="description" class="text">{{ description }}</p>
<div class="inner" :style="rows">
<div
class="option"
v-for="(option, index) in options"
:key="index"
@click="emitInput"
>
<div class="borderline">
<div :class="isSelected(option)"/>
</div>
<p class="label">{{ getLabel(option) }}</p>
</div>
</div>
</c-input-container>
</template>
<script>
import CInputContainer from '../CInputContainer'
/**
* A radio button component. When an option is selected, it emits an 'input'
* event with the chosen option.
*/
export default {
name: 'CRadioButton',
components: { CInputContainer },
props: {
/**
* Array of strings or objects
*/
options: {
type: Array,
default: () => ([])
},
/**
* If `options` is an array of objects, CRadioButon will use this prop
* to compare the currently selected item.
*/
trackBy: {
type: String,
default: ''
},
/**
* If `options` is an array of objects, CRadioButton will use this prop
* to get the label of the option/value to be displayed for the user.
*/
displayBy: {
type: String,
default: ''
},
/**
* Number of columns
*/
columns: {
type: Number,
default: 1
},
/**
* Selected option's value
*/
value: {
type: [Object, String, Boolean],
default: ''
},
/**
* Radio button description
*/
description: {
type: String,
default: ''
}
},
computed: {
rows() {
return 'grid-template-rows: repeat(' + Math.ceil(this.options.length/this.columns) + ', 1fr);'
},
},
methods: {
isSelected(option) {
if (this.trackBy && option instanceof Object) {
return this.value instanceof Object
? this.value[this.trackBy] === option[this.trackBy] ? 'selected' : 'unselected'
: this.value === option[this.trackBy] ? 'selected' : 'unselected'
}
return this.value === option
? 'selected'
: 'unselected'
},
emitInput (option) {
const value = this.trackBy && option instanceof Object && !(this.value instanceof Object)
? option[this.trackBy]
: option
this.$emit('input', value)
},
getLabel(option) {
if (this.displayBy && option instanceof Object) {
return option[this.displayBy]
}
return option
}
}
}
</script>
<style lang="scss">
.c-radio-button {
& > .text { margin-bottom: 20px; }
& > .inner {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
grid-column-gap: 30px;
grid-row-gap: 15px;
justify-content: space-around;
& > .option {
display: flex;
flex-flow: row;
align-items: center;
& > .borderline {
display: flex;
flex-flow: row;
align-items: center;
justify-content: center;
min-width: 25px;
max-width: 25px;
min-height: 25px;
max-height: 25px;
border: 1px solid $base-border-color;
border-radius: 50%;
background-color: white;
& > .selected {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: map-get($disabled-color-map, dark);
transition: width .4s, height .4s;
transition-timing-function: cubic-bezier(.45,1.8,.5,.75);
}
& > .unselected {
width: 0;
height: 0;
}
}
& > .label {
vertical-align: middle;
margin-left: 10px;
font-size: 14px;
color: map-get($disabled-color-map, dark);
}
}
}
& > .jumbo-validation { display: none; }
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment