DropdownLink.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <template>
  2. <div
  3. class="dropdown-wrapper"
  4. :class="{ open }"
  5. >
  6. <button
  7. class="dropdown-title"
  8. type="button"
  9. :aria-label="dropdownAriaLabel"
  10. @click="setOpen(!open)"
  11. >
  12. <span class="title">{{ item.text }}</span>
  13. <span
  14. class="arrow"
  15. :class="open ? 'down' : 'right'"
  16. />
  17. </button>
  18. <DropdownTransition>
  19. <ul
  20. v-show="open"
  21. class="nav-dropdown"
  22. >
  23. <li
  24. v-for="(subItem, index) in item.items"
  25. :key="subItem.link || index"
  26. class="dropdown-item"
  27. >
  28. <h4 v-if="subItem.type === 'links'">
  29. {{ subItem.text }}
  30. </h4>
  31. <ul
  32. v-if="subItem.type === 'links'"
  33. class="dropdown-subitem-wrapper"
  34. >
  35. <li
  36. v-for="childSubItem in subItem.items"
  37. :key="childSubItem.link"
  38. class="dropdown-subitem"
  39. >
  40. <NavLink
  41. :item="childSubItem"
  42. @focusout="
  43. isLastItemOfArray(childSubItem, subItem.items) &&
  44. isLastItemOfArray(subItem, item.items) &&
  45. setOpen(false)
  46. "
  47. />
  48. </li>
  49. </ul>
  50. <NavLink
  51. v-else
  52. :item="subItem"
  53. @focusout="isLastItemOfArray(subItem, item.items) && setOpen(false)"
  54. />
  55. </li>
  56. </ul>
  57. </DropdownTransition>
  58. </div>
  59. </template>
  60. <script>
  61. import NavLink from '@theme/components/NavLink.vue'
  62. import DropdownTransition from '@theme/components/DropdownTransition.vue'
  63. import last from 'lodash/last'
  64. export default {
  65. name: 'DropdownLink',
  66. components: {
  67. NavLink,
  68. DropdownTransition
  69. },
  70. props: {
  71. item: {
  72. required: true
  73. }
  74. },
  75. data () {
  76. return {
  77. open: false
  78. }
  79. },
  80. computed: {
  81. dropdownAriaLabel () {
  82. return this.item.ariaLabel || this.item.text
  83. }
  84. },
  85. watch: {
  86. $route () {
  87. this.open = false
  88. }
  89. },
  90. methods: {
  91. setOpen (value) {
  92. this.open = value
  93. },
  94. isLastItemOfArray (item, array) {
  95. return last(array) === item
  96. }
  97. }
  98. }
  99. </script>
  100. <style lang="stylus">
  101. .dropdown-wrapper
  102. cursor pointer
  103. .dropdown-title
  104. display block
  105. font-size 0.9rem
  106. font-family inherit
  107. cursor inherit
  108. padding inherit
  109. line-height 1.4rem
  110. background transparent
  111. border none
  112. font-weight 500
  113. color $textColor
  114. &:hover
  115. border-color transparent
  116. .arrow
  117. vertical-align middle
  118. margin-top -1px
  119. margin-left 0.4rem
  120. .nav-dropdown
  121. .dropdown-item
  122. color inherit
  123. line-height 1.7rem
  124. h4
  125. margin 0.45rem 0 0
  126. border-top 1px solid #eee
  127. padding 0.45rem 1.5rem 0 1.25rem
  128. .dropdown-subitem-wrapper
  129. padding 0
  130. list-style none
  131. .dropdown-subitem
  132. font-size 0.9em
  133. a
  134. display block
  135. line-height 1.7rem
  136. position relative
  137. border-bottom none
  138. font-weight 400
  139. margin-bottom 0
  140. padding 0 1.5rem 0 1.25rem
  141. &:hover
  142. color $accentColor
  143. &.router-link-active
  144. color $accentColor
  145. &::after
  146. content ""
  147. width 0
  148. height 0
  149. border-left 5px solid $accentColor
  150. border-top 3px solid transparent
  151. border-bottom 3px solid transparent
  152. position absolute
  153. top calc(50% - 2px)
  154. left 9px
  155. &:first-child h4
  156. margin-top 0
  157. padding-top 0
  158. border-top 0
  159. @media (max-width: $MQMobile)
  160. .dropdown-wrapper
  161. &.open .dropdown-title
  162. margin-bottom 0.5rem
  163. .dropdown-title
  164. font-weight 600
  165. font-size inherit
  166. &:hover
  167. color $accentColor
  168. .nav-dropdown
  169. transition height .1s ease-out
  170. overflow hidden
  171. .dropdown-item
  172. h4
  173. border-top 0
  174. margin-top 0
  175. padding-top 0
  176. h4, & > a
  177. font-size 15px
  178. line-height 2rem
  179. .dropdown-subitem
  180. font-size 14px
  181. padding-left 1rem
  182. @media (min-width: $MQMobile)
  183. .dropdown-wrapper
  184. height 1.8rem
  185. &:hover .nav-dropdown,
  186. &.open .nav-dropdown
  187. // override the inline style.
  188. display block !important
  189. &.open:blur
  190. display none
  191. .dropdown-title .arrow
  192. // make the arrow always down at desktop
  193. border-left 4px solid transparent
  194. border-right 4px solid transparent
  195. border-top 6px solid $arrowBgColor
  196. border-bottom 0
  197. .nav-dropdown
  198. display none
  199. // Avoid height shaked by clicking
  200. height auto !important
  201. box-sizing border-box;
  202. max-height calc(100vh - 2.7rem)
  203. overflow-y auto
  204. position absolute
  205. top 100%
  206. right 0
  207. background-color #fff
  208. padding 0.6rem 0
  209. border 1px solid #ddd
  210. border-bottom-color #ccc
  211. text-align left
  212. border-radius 0.25rem
  213. white-space nowrap
  214. margin 0
  215. </style>