SelectFilter.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <template>
  2. <menu-tooltip v-model='menuOpen'>
  3. <button
  4. slot='button'
  5. class='button select_filter__button'
  6. :class='{ "select_filter__button--selected": menuOpen }'
  7. @click='menuOpen = true'
  8. >
  9. {{name}}
  10. <span class='fa fa-chevron-down'></span>
  11. </button>
  12. <template slot='menu'>
  13. <div
  14. class='select_filter__item select_filter__item--select_all'
  15. @click='toggleSelectAll'
  16. >
  17. <div
  18. class='select_filter__checkbox'
  19. :class='{ "select_filter__checkbox--selected": selected.length === options.length }'
  20. ></div>
  21. <span>Select all</span>
  22. </div>
  23. <div
  24. class='select_filter__item'
  25. v-for='(item, $index) in options'
  26. @click='toggledSelectItem($index)'
  27. >
  28. <div
  29. class='select_filter__checkbox'
  30. :class='{ "select_filter__checkbox--selected": selected.includes($index) }'
  31. ></div>
  32. <span>{{item.name}}</span>
  33. </div>
  34. </template>
  35. </menu-tooltip>
  36. </template>
  37. <script>
  38. import MenuTooltip from './MenuTooltip';
  39. export default {
  40. name: 'SelectFilter',
  41. props: ['name', 'options', 'value'],
  42. components: {
  43. MenuTooltip
  44. },
  45. data () {
  46. return {
  47. menuOpen: false,
  48. selected: []
  49. }
  50. },
  51. methods: {
  52. toggleSelectAll () {
  53. //If everything is selected
  54. if(this.selected.length === this.options.length) {
  55. this.selected = [];
  56. } else {
  57. this.selected = this.options.map((_, i) => i);
  58. }
  59. },
  60. toggledSelectItem (itemIndex) {
  61. let selectedArrIndex = this.selected.indexOf(itemIndex);
  62. if(selectedArrIndex === -1) {
  63. this.selected.push(itemIndex);
  64. } else {
  65. this.selected.splice(selectedArrIndex, 1);
  66. }
  67. }
  68. },
  69. watch: {
  70. selected () {
  71. let selectedItems = this.options.filter((item, index) => {
  72. return this.selected.includes(index);
  73. });
  74. this.$emit('value', selectedItems);
  75. }
  76. },
  77. mounted () {
  78. this.toggleSelectAll();
  79. }
  80. }
  81. </script>
  82. <style lang='scss' scoped>
  83. @import '../assets/scss/variables.scss';
  84. .select_filter {
  85. @at-root #{&}__button {
  86. border-radius: 0.25rem;
  87. cursor: pointer;
  88. font-weight: normal;
  89. position: relative;
  90. transition: color 0.2s, border-color 0.2s;
  91. &:hover {
  92. color: $color__blue--darker;
  93. }
  94. span.fa {
  95. font-size: 0.7rem;
  96. transform: rotate(0deg) translateY(-0.1rem);
  97. transition: transform 0.2s;
  98. }
  99. @at-root #{&}--selected {
  100. color: $color__blue--darker !important;
  101. span.fa {
  102. transform: rotate(180deg) translateY(0rem);
  103. }
  104. }
  105. }
  106. @at-root #{&}__item {
  107. align-items: center;
  108. background-color: #fff;
  109. border-radius: 0.25rem;
  110. cursor: default;
  111. display: grid;
  112. font-size: 0.9rem;
  113. font-weight: normal;
  114. grid-column-gap: 0.5rem;
  115. grid-template-columns: 1rem auto;
  116. justify-items: start;
  117. padding: 0.125rem 0.25rem;
  118. user-select: none;
  119. transition: background-color 0.2s;
  120. &:hover {
  121. background-color: $color__lightgray--darker;
  122. }
  123. @at-root #{&}--select_all {
  124. font-weight: 600;
  125. }
  126. }
  127. @at-root #{&}__checkbox {
  128. background-color: #fff;
  129. border: thin solid $color__gray--darkest;
  130. border-radius: 0.25rem;
  131. height: 1rem;
  132. width: 1rem;
  133. transition: all 0.2s;
  134. @at-root #{&}--selected {
  135. background-color: $color__blue--darker;
  136. border: thin solid $color__blue--primary;
  137. box-shadow: 0 0 0 1.5px $color__blue--primary inset;
  138. }
  139. }
  140. }
  141. @media (max-width: $breakpoint--tablet) {
  142. .select_filter__item {
  143. font-size: 1.125rem;
  144. padding: 0.5rem 0.75rem;
  145. }
  146. }
  147. </style>