FormToggle.vue 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <script setup>
  2. import { useIdGenerator, useValidationErrorIdGenerator } from '@/composables/helpers'
  3. import { UseColorMode } from '@vueuse/components'
  4. const props = defineProps({
  5. modelValue: [String, Number, Boolean],
  6. choices: {
  7. type: Array,
  8. required: true
  9. },
  10. fieldName: {
  11. type: String,
  12. required: true
  13. },
  14. fieldError: [String],
  15. hasOffset: Boolean,
  16. isDisabled: Boolean,
  17. isLocked: Boolean,
  18. label: {
  19. type: String,
  20. default: ''
  21. },
  22. help: {
  23. type: String,
  24. default: ''
  25. },
  26. })
  27. // defines what events our component emits
  28. const emit = defineEmits(['update:modelValue'])
  29. const { valErrorId } = useValidationErrorIdGenerator(props.fieldName)
  30. const legendId = useIdGenerator('legend', props.fieldName).inputId
  31. function setRadio(event) {
  32. emit('update:modelValue', event)
  33. }
  34. </script>
  35. <template>
  36. <div class="field" :class="{ 'pt-3': hasOffset }">
  37. <span v-if="label" class="label" :class="{ 'is-opacity-5' : isDisabled || isLocked }">
  38. {{ $t(label) }}<FontAwesomeIcon v-if="isLocked" :icon="['fas', 'lock']" class="ml-2" size="xs" />
  39. </span>
  40. <div
  41. id="rdoGroup"
  42. role="radiogroup"
  43. :aria-describedby="help ? legendId : undefined"
  44. :aria-invalid="fieldError != undefined"
  45. :aria-errormessage="fieldError != undefined ? valErrorId : undefined"
  46. class="is-toggle buttons"
  47. >
  48. <UseColorMode v-slot="{ mode }">
  49. <button
  50. v-for="choice in choices"
  51. :key="choice.value"
  52. :id="useIdGenerator('button',fieldName+choice.value).inputId"
  53. role="radio"
  54. type="button"
  55. class="button"
  56. :aria-checked="modelValue===choice.value"
  57. :disabled="isDisabled || isLocked"
  58. :class="{
  59. 'is-link': modelValue===choice.value,
  60. 'is-dark': mode==='dark',
  61. 'is-multiline': choice.legend,
  62. }"
  63. v-on:click.stop="setRadio(choice.value)">
  64. <input
  65. :id="useIdGenerator('radio',choice.value).inputId"
  66. type="radio"
  67. class="is-hidden"
  68. :checked="modelValue===choice.value"
  69. :value="choice.value"
  70. :disabled="isDisabled || isLocked"
  71. />
  72. <span v-if="choice.legend" v-html="$t(choice.legend)" class="is-block is-size-7" />
  73. <FontAwesomeIcon :icon="['fas',choice.icon]" v-if="choice.icon" class="mr-2" />
  74. <label :for="useIdGenerator('button',fieldName+choice.value).inputId" class="is-clickable">
  75. {{ $t(choice.text) }}
  76. </label>
  77. </button>
  78. </UseColorMode>
  79. </div>
  80. <FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
  81. <p :id="legendId" class="help" v-html="$t(help)" v-if="help" />
  82. </div>
  83. </template>