DigitalConsumer.ISS/src/ux-components/radio/radio.vue
2023-07-24 14:27:39 -04:00

156 lines
4 KiB
Vue

<template>
<!-- Checkbox groups MUST be wrapped in a <fieldset> and <legend> tag and must contain tabindex -->
<div
class="ui-radio form-check"
:class="[(errors.length > 0 || hasError) ? 'has-error' : '']">
<label
class="d-inline-flex align-items-start form-check-label"
:for="buttonID">
<input
:id="buttonID"
type="radio"
class="form-check-input"
aria-checked="false"
:name="groupName"
:aria-required="isRequired"
:value="value"
:v-model="checkValue"
:checked="checkValue"
:validationRules="validationRules"
@change="handleCheckChange" />
<p
v-if="buttonLabel"
class="m-0">{{ buttonLabel }}</p>
<span
v-if="screenReaderOnlyText"
class="sr-only">
{{ screenReaderOnlyText }}
</span>
</label>
</div>
</template>
<script>
import { useField } from 'vee-validate';
export default {
name: 'radio',
props: {
groupName: String,
buttonLabel: String,
buttonID: String,
isRequired: Boolean,
value: {
type: [String, Number],
default: ''
},
screenReaderOnlyText: String,
selectedValues: String,
hasError: Boolean,
validationRules: String,
valueToLogType: String
},
emits: ['isCheckedChanged', 'update:modelValue'],
setup(props) {
const inputType = 'radio';
const {
value: inputValue,
handleChange,
errors,
resetField
} = useField(props.groupName, props.validationRules, {
type: inputType
});
return {
handleChange,
errors,
resetField
};
},
data() {
return {
checkValue: Boolean
};
},
created() {
if (this.selectedValues) {
this.checkValue = this.selectedValues === this.value;
this.handleCheckChange();
} else {
this.checkValue = false;
}
},
unmounted() {
this.resetField();
},
methods: {
handleCheckChange() {
this.handleChange(this.value);
const emitEvent = {
checkValue: this.checkValue,
value: this.value.toString(),
buttonID: this.buttonID && this.buttonID.toString()
};
this.$emit('isCheckedChanged', emitEvent);
this.$emit('update:modelValue', emitEvent);
}
}
};
</script>
<style lang="scss" scoped>
.form-check {
position: relative;
label {
&:hover {
cursor: pointer;
}
}
.form-check-input {
border: 1px solid $gray-500;
border-radius: 50%;
margin-right: 0.5rem;
&:checked {
background-color: $white;
background-size: 71%;
background-position: center;
border: 1px solid $blue;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50' xml:space='preserve'%3e%3ccircle cx='25' cy='25' r='25' fill='%231574A1'/%3e%3c/svg%3e");
+ label {
p {
font-weight: 500;
font-size: .875rem;
color: $black;
}
}
}
&:focus {
box-shadow: 0 0 0 2.5px $blue;
}
&, & + label {
margin-top: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
}
&:hover {
.form-check-input {
box-shadow: 0 0 0 4px $blue-300;
}
}
p {
font-weight: 400;
font-size: .875rem;
color: $gray-600;
}
}
</style>