Skip to content

Instantly share code, notes, and snippets.

@iErik
Created February 11, 2019 15:41
Show Gist options
  • Select an option

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

Select an option

Save iErik/63776186da504f6ad6490872253e1299 to your computer and use it in GitHub Desktop.
<template>
<c-input-container v-bind="$attrs" class="c-radio-button">
<div class="inner" :style="rows">
<div
class="option"
v-for="(option, index) in options"
:key="index"
@click="$emit('input', option)"
>
<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: ''
}
},
computed: {
rows() {
return 'grid-template-rows: repeat(' + ~~(this.options.length/this.columns) + ', 1fr);'
},
},
methods: {
isSelected(option) {
if (this.trackBy && option instanceof Object) {
return this.value[this.trackBy] === option[this.trackBy]
? 'selected'
: 'unselected'
}
return this.value === option
? 'selected'
: 'unselected'
},
getLabel(option) {
if (this.displayBy && option instanceof Object) {
return option[this.displayBy]
}
return option
}
}
}
</script>
<style lang="scss">
.c-radio-button > .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;
width: 25px;
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: 15px;
color: map-get($disabled-color-map, dark);
}
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment