SelectButton.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <div class='select_button' :class='{"select_button--touch": !touchDisabled}'>
  3. <div
  4. class='select_button__overlay'
  5. :class='{ "select_button__overlay--show": !hideMenu }'
  6. @click='toggleMenu'
  7. ></div>
  8. <div class='button button--thin_text' @click='toggleMenu' v-if='options.length'>
  9. {{options[selectedIndex].name}}
  10. <span class='button__icon fa fa-fw' :class='[hideMenu ? "fa-caret-down" : "fa-caret-up"]'></span>
  11. </div>
  12. <div class='button' v-else>
  13. No options
  14. </div>
  15. <div class='select_button__options' :class='{"select_button__options--hidden": hideMenu}'>
  16. <div
  17. v-for='(option, index) in options'
  18. @click='select(index, option.disabled)'
  19. class='select_button__option'
  20. :class='{"select_button__option--disabled": option.disabled}'
  21. >
  22. {{option.name}}
  23. </div>
  24. </div>
  25. </div>
  26. </template>
  27. <script>
  28. export default {
  29. name: 'SelectButton',
  30. props: ['options', 'value', 'name', 'touch-disabled'],
  31. methods: {
  32. toggleMenu () {
  33. this.hideMenu = !this.hideMenu;
  34. },
  35. select (index, disabled) {
  36. if(disabled) return;
  37. this.selectedIndex = index;
  38. this.hideMenu = true;
  39. this.$emit('input', this.options[index].value);
  40. },
  41. getIndexFromValue () {
  42. var index = 0;
  43. var self = this;
  44. if(this.value !== null) {
  45. this.options.forEach((option, i) => {
  46. if(option.value === self.value) {
  47. index = i;
  48. }
  49. })
  50. }
  51. return index;
  52. }
  53. },
  54. data () {
  55. return {
  56. selectedIndex: this.getIndexFromValue(),
  57. hideMenu: true
  58. }
  59. },
  60. watch: {
  61. value () {
  62. this.selectedIndex = this.getIndexFromValue();
  63. }
  64. }
  65. }
  66. </script>
  67. <style lang='scss' scoped>
  68. @import '../assets/scss/variables.scss';
  69. .select_button {
  70. display: inline-block;
  71. @at-root #{&}__overlay {
  72. position: fixed;
  73. width: 100%;
  74. height: 100%;
  75. left: 0;
  76. top: 0;
  77. z-index: 2;
  78. pointer-events: none;
  79. @at-root #{&}--show {
  80. pointer-events: all;
  81. }
  82. }
  83. @at-root #{&}__options {
  84. position: absolute;
  85. z-index: 3;
  86. overflow: hidden;
  87. background-color: #fff;
  88. width: 15rem;
  89. border: 1px solid $color__gray--darker;
  90. margin-top: 0.125rem;
  91. max-height: 20rem;
  92. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.03), 0 3px 6px rgba(0, 0, 0, 0.12);
  93. transition: max-height 0.4s ease-out;
  94. border-radius: 0.2rem;
  95. @include user-select(none);
  96. @at-root #{&}--hidden {
  97. max-height: 0;
  98. box-shadow: none;
  99. border-color: transparent;
  100. background-color: transparent;
  101. transition: max-height 0.2s ease-out, box-shadow 0.2s, border-color 0s ease-in 0.19s, background-color 0s ease-in 0.19s;
  102. }
  103. }
  104. @at-root #{&}__option {
  105. padding: 0.25rem 0.5rem;
  106. transition: background-color 0.2s;
  107. cursor: default;
  108. &:hover {
  109. background-color: $color__lightgray--primary;
  110. }
  111. &:active {
  112. background-color: darken($color__lightgray--primary, 2%);
  113. }
  114. @at-root #{&}--disabled {
  115. color: $color__gray--darkest;
  116. pointer-events: none;
  117. }
  118. }
  119. }
  120. @media (max-width: 425px) {
  121. .select_button__option {
  122. font-size: 1.125rem;
  123. padding: 0.5rem 0.75rem;
  124. }
  125. .select_button--touch {
  126. .select_button {
  127. @at-root #{&}__overlay {
  128. transition: all 0.2s;
  129. @at-root #{&}--show {
  130. background-color: hsla(213, 35%, 5%, 0.5);
  131. }
  132. }
  133. @at-root #{&}__options {
  134. width: 100%;
  135. left: 0;
  136. bottom: 0;
  137. position: fixed;
  138. font-size: 1.125rem;
  139. opacity: 1;
  140. border-radius: 0.25rem 0.25rem 0 0;
  141. transition: opacity 0.2s, bottom 0.2s;
  142. background-color: rgba(255, 255, 255, 0.97);
  143. @at-root #{&}--hidden {
  144. bottom: -100%;
  145. opacity: 0;
  146. }
  147. }
  148. @at-root #{&}__option {
  149. padding: 0.75rem;
  150. }
  151. }
  152. }
  153. }
  154. </style>